[M1: Audit 2: L-04]: CIP112: Pass consumed holdings to createHolding so consumer fields survive re-creation

Open
#89 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
Feature
Clarity
Clearly specified
Activity status
Active
Domain
blockchain

Research direction

Start with packages/token/token-cip112-utils/daml/OpenZeppelin/Token/Cip112/Utils/Holding.daml and its createHolding and consumeHolding operations, then trace the listed re-creation paths in Transfer.daml and Allocation.daml. Read the token-cip112-utils README.md for the documentation requirements. Done means consumed holding fields survive across every specified workflow, mint uses closure defaults, and the docs explain reset behavior and where in-flight state belongs; add the requested test-package coverage.

Written by the indexing model from the issue text.

Description

Addresses L-04

Problem

HoldingOps.createHolding receives only a standard HoldingView. Every workflow path that consumes a holding and creates a replacement builds the new contract from the closure's defaults, so consumer template fields (a freeze flag, a tag, a tier, an issue timestamp) reset on every re-creation. The re-creation paths are:

A consumer can't carry state across these paths, and the HoldingOps documentation doesn't warn that the state is lost. The default TokenHolding has no extra fields and isn't affected.

The example's compliance freeze is tracked separately in #82, which moves the freeze to a per-account status contract.

Changes

Code:

  • createHolding should receive the holdings consumed to produce the new one: their template values, or at least their views. Each workflow path passes its consumed inputs, a mint passes none, and the consumer's closure decides which fields to carry over.
  • consumeHolding should return whatever createHolding needs, so the workflows can pass it along without fetching the holdings again.
  • Update the TokenHolding ops to the new signature. Its behaviour doesn't change.

Documentation:

  • The HoldingOps doc comment and the token-cip112-utils README.md should state which consumed holdings each path passes to createHolding, and that any field the closure doesn't derive from them resets on re-creation.
  • They should also state that state which must hold while funds are in flight belongs on a separate per-account contract, not on the holding: the spend hook refuses such holdings, so no re-creation path consumes them.

Tests:

  • In a test package, add a holding template with an extra field and a createHolding that copies the field from the consumed holdings. Check that the field is still on the holding a workflow returns, for every path:
    • Transfers: sender change, then reject, withdraw and expire of the pending transfer. The returned holding should still carry the field from the original holding, which shows the locked holding carried it through the pending period.
    • Allocations: change and the locked holding at allocation time, then cancel, withdraw and expire of the pending allocation, and the reserve on settlement.
    • Owner unlock of an expired locked holding.
  • Check that a mint, which consumes nothing, creates the holding with the closure's defaults.
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.