Problem
Three flaws combine to make the parameters-contract multisig (contracts/parameters-contract/src/lib.rs) provide theater, not security:
- Admin bypass:
configure_multisig() (lines 41–57) requires only the single admin key's auth. The same admin retains do_set_admin() reachability through proposals AND direct set_admin-style power elsewhere in the protocol. A single compromised key can reconfigure or sidestep the entire "multisig".
- Stale approvals survive signer-set changes: proposals store
approvals: Vec<Address> (lines 79–91). If UpdateSigners executes and removes a signer, that removed signer's approval remains counted by execute() (line 132 checks only approvals.len() >= threshold). Revoked signers retain veto/exec power over in-flight proposals.
- Self-serving threshold reduction: a signer set at threshold 2-of-3 can propose
UpdateSigners to 2-of-2 (or admit a colluder); execute() validates against the CURRENT config, so the proposal needs only old-threshold approvals to install a weaker future threshold. There is no escalation guard requiring higher quorum for signer-set changes.
Combined: one colluding signer plus one stale approval can rewrite parameters (interest bps, min guarantee, grace periods) that directly control creditline economics.
Ground Rules
- Read context/architecture-context.md, context/code-standards.md, context/progress-tracker.md in full
- Read parameters-contract in full including storage.rs and types.rs (
MultisigConfig, Proposal)
- Preserve the existing event surface where possible; additive changes only
What To Build
- Record the snapshot of eligible signer addresses (not just a count) at proposal time;
approve() and execute() must validate each approver against the snapshot AND current membership, rejecting anyone removed since.
- Require a strictly higher quorum for
UpdateSigners actions (e.g. threshold + 1 or full unanimity — pick and document one) so signers cannot cheapen their own gate.
- On
configure_multisig, emit a prominent event and consider a two-step confirmation (propose→confirm) so a single admin key cannot silently swap the signer set.
- Clear/re-validate in-flight proposals whose action targets the signer set when the signer set changes.
- Tests for every branch above, including the stale-approval exploit reproducing end-to-end before the fix and failing after.
Files To Touch
contracts/parameters-contract/src/lib.rs
contracts/parameters-contract/src/storage.rs
contracts/parameters-contract/src/types.rs
contracts/parameters-contract/src/tests.rs
context/progress-tracker.md
Acceptance Criteria
Mandatory Checks Before Opening PR
PRs failing any check will be closed without review.
Problem
Three flaws combine to make the parameters-contract multisig (contracts/parameters-contract/src/lib.rs) provide theater, not security:
configure_multisig()(lines 41–57) requires only the single admin key's auth. The same admin retainsdo_set_admin()reachability through proposals AND directset_admin-style power elsewhere in the protocol. A single compromised key can reconfigure or sidestep the entire "multisig".approvals: Vec<Address>(lines 79–91). IfUpdateSignersexecutes and removes a signer, that removed signer's approval remains counted byexecute()(line 132 checks onlyapprovals.len() >= threshold). Revoked signers retain veto/exec power over in-flight proposals.UpdateSignersto 2-of-2 (or admit a colluder);execute()validates against the CURRENT config, so the proposal needs only old-threshold approvals to install a weaker future threshold. There is no escalation guard requiring higher quorum for signer-set changes.Combined: one colluding signer plus one stale approval can rewrite parameters (interest bps, min guarantee, grace periods) that directly control creditline economics.
Ground Rules
MultisigConfig,Proposal)What To Build
approve()andexecute()must validate each approver against the snapshot AND current membership, rejecting anyone removed since.UpdateSignersactions (e.g.threshold + 1or full unanimity — pick and document one) so signers cannot cheapen their own gate.configure_multisig, emit a prominent event and consider a two-step confirmation (propose→confirm) so a single admin key cannot silently swap the signer set.Files To Touch
contracts/parameters-contract/src/lib.rscontracts/parameters-contract/src/storage.rscontracts/parameters-contract/src/types.rscontracts/parameters-contract/src/tests.rscontext/progress-tracker.mdAcceptance Criteria
Mandatory Checks Before Opening PR
PRs failing any check will be closed without review.