Skip to content

move delegation split invariants onto the template's ensure clause #286

Description

@gyorgybalazsi

Summary

Every guard on the delegation's split lives in one governable action's executeImpl (SetupCouponReassignmentDelegation.daml): non-empty beneficiaries, ≤20, percentages in (0,1] summing to exactly 1.0, uniqueness, non-empty assigners, unique assigners, and the decparty/dso exclusions.

CouponReassignmentDelegation itself has no ensure clause. So the invariants hold for the one creation path that exists today, and for no other.

Why it matters

Any future creation path bypasses all of them: a second governable action (a migration action, a differently-shaped setup), or a direct threshold submit by the decparty. Such a path could create a delegation whose split is empty, sums to 0.7, or repeats a beneficiary — and the last of those is not merely wrong but permanently un-exerciseable, because splice's RewardCoupon_AssignBeneficiaries requires unique beneficiaries. With a failed chunk ending the tick, that coupon then heads the most-urgent-first order forever and assignment stalls behind it.

The guards are also duplicated against Rust's validate_reward_beneficiaries, so there are already two copies of the rules and a third creation path would need a fourth.

Requirements

  1. Move the split invariants onto CouponReassignmentDelegation as an ensure clause, so they hold for every creation path rather than one.
  2. executeImpl keeps whatever is genuinely about the action rather than the contract — the priorDelegation revoke, and any check that needs the proposer's context.
  3. The existing execute-time tests must keep passing unchanged; add a direct-create negative proving the template itself rejects a bad split (there is currently no such test — given_delegation only ever creates a valid one).
  4. Note that ensure cannot express the dso/decparty exclusions if they need the governance party's identity beyond what the template already carries; keep those in executeImpl and say why in a comment.

References

  • daml/governance-rewards/daml/Governance/Rewards/SetupCouponReassignmentDelegation.damlexecuteImpl, all guards.
  • daml/governance-rewards/daml/Governance/Rewards/CouponReassignmentDelegation.daml — the template, no ensure.
  • crates/decman/src/server/types.rsvalidate_reward_beneficiaries, the API-boundary copy.

Metadata

Metadata

Assignees

No one assigned

    Labels

    maintenanceMaintenance and hardening workrustPull requests that update rust code

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions