[M1: Audit 2: L-05]: CIP112: Split `consumeHolding` into a spend hook and a release hook

Open
#90 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
48/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Domain
blockchain

Research direction

Start with HoldingOps in packages/token/token-cip112-utils/daml/OpenZeppelin/Token/Cip112/Utils/Holding.daml and trace how consumeUnlockedHolding, consumeLockedHolding and unlockHoldings are used. Then check the token-cip112-v1 implementation, the custom example, and the trust-boundary section of the README. Done means spend rules apply only to caller-supplied inputs, locked funding can be released on every listed workflow path, and regression tests, comments and the changelog reflect the change.

Written by the indexing model from the issue text.

Description

Addresses L-05

HoldingOps.consumeHolding does two jobs: it checks that a holding is an accepted implementation, and it is the spend hook. The workflows call it on caller-supplied inputs and also on funding they locked themselves. As a result, a spend rule placed in it runs on accept, reject, withdraw, expire, settle and cancel. A minimum-age rule blocks the receiver's accept and reject, and the sender's withdraw, until the funding is old enough. A rule that never passes for workflow-created holdings blocks every return path until lockExpiresAt. After that, only holdingOwnerUnlockImpl can recover the funds.

Changes

Code:

  • Replace consumeHolding in HoldingOps with two operations:
    • spendHolding for caller-supplied inputs: the accepted-implementation check plus the consumer's spend rules. Called by consumeUnlockedHolding in the transfer and allocation factories.
    • releaseHolding for funding the workflow locked: the accepted-implementation check only. Called by consumeLockedHolding and unlockHoldings on accept, reject, withdraw, expire, settle and cancel.
  • Set both operations to consumeByArchive @TokenHolding in token-cip112-v1.
  • In the custom example, keep MyHolding_Spend behind spendHolding and set releaseHolding to consumeByArchive @MyHolding.

Documentation:

  • Update the HoldingOps doc comment and the trust boundary section of the token-cip112-utils README.md. Both should name the workflow paths that call each hook, and state that releaseHolding must not reject a holding the workflow locked.
  • Update the custom example module comment, which says the freeze refuses every workflow path.
  • Add a CHANGELOG.md entry for the HoldingOps change.

Tests:

  • Add a case where spendHolding rejects the locked funding, for example with a minimum-age rule, and check that accept, reject, withdraw, expire, settle and cancel still succeed.
Dominant language
Haskell
Stars
5
Forks
0
Avg merge
1d 36m
Merged PRs (30d)
11

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from OpenZeppelin/canton-contracts

All issues in OpenZeppelin/canton-contracts

Similar issues

More Haskell issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.