Skip to content

Drop the strict ascending-address ordering requirement on multi-sig upgrade approvals #304

Description

@N-thnI

Description

Remove an undocumented ordering constraint that can deadlock a pending upgrade.

Problem Statement

approve_upgrade rejects any approval whose address does not sort strictly after the last recorded one (src/contracts/upgrade.rs:236-240, and identically at 153-157):

if let Some(previous) = approvals.last() {
    if previous >= signer {
        return Err(ContractError::InvalidUpgradeConfig);
    }
}

Duplicate approvals are already rejected two lines above by approvals.contains(signer.clone()), so this adds nothing except a hidden constraint on the order signers happen to transact in.

Verified against current main: with signers [A, B, C] sorted ascending and threshold 2, if B proposes first, A's subsequent approve_upgrade returns Err(InvalidUpgradeConfig) — and there is no way to withdraw B's approval, so the proposal can only ever be completed by C. With threshold equal to the signer count, a single out-of-order proposal deadlocks the upgrade until an admin calls cancel_upgrade.

It's also undocumented: the # Errors list at src/contracts/upgrade.rs:203-206 names only NotUpgradeSigner, NoPendingUpgrade, and AlreadyApproved. Every test in tests/upgrade.rs approves in ascending order, so the case is untested.

Proposed Changes

  • Delete the previous >= signer check from both approve_upgrade and propose_upgrade; rely on approvals.contains(...) for dedup
  • Keep is_strictly_sorted_addresses on the set_upgrade_signers configuration list (src/contracts/upgrade.rs:63) — canonical ordering is meaningful there
  • If the sorted-approvals invariant is genuinely wanted for cheap membership checks, insert in sorted position rather than rejecting

Technical Implementation Scaffolding

  • Target Repository: vero-core-contracts
  • Target Path: src/contracts/upgrade.rs
  • Branch Naming: fix/issue--upgrade-approval-ordering
  • Authority Context: Security-sensitive — contract upgrade governance

Acceptance Criteria

  • With sorted signers [A, B, C] and threshold 2, propose_upgrade(B) followed by approve_upgrade(A) succeeds
  • Approving twice from the same address still returns AlreadyApproved
  • All three signers can approve in any of the 6 permutations and execute_upgrade succeeds in each

Definition of Done

  • Reviewed by lead maintainer
  • Pull request merged via verified status check

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardThird CampaignCampaign: Third Campaign

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions