s_signers list lead to permanent Multi-Sig Wallet LockThe MultiSigTimelock contract inherits from OpenZeppelin's AccessControl contract for permission management. AccessControl includes a public function renounceRole which allows an signer to unilaterally relinquish its assigned role SIGNING_ROLE without authorization from the contract Owner.
However, MultiSigTimelock implements internal tracking of active signers through a custom s_signerCount counter and an s_isSigner mapping. Since the contract fails to override the inherited renounceRole function, any signer who renounces their role will trigger a state mismatch: the role is removed at the AccessControl level, but the internal s_signerCount and s_isSigner states remain unchanged.
Likelihood: High
Any signer can call function renounceRole.
Impact:
Renouncing roles prevents the quorum from being met and freezes transaction execution, while the stale s_signerCount blocks the Owner from adding new signers, effectively allowing the authorized signer count to drop to zero and bypassing the "at least one signer" safety rule.
Three signers unilaterally renounce their roles, proving they can exit without Owner approval.
The test confirms "Ghost Signers" exist because the registry still lists addresses that no longer hold signing roles.
The expectRevert proves the Owner is blocked from adding new signers because the stale counter falsely indicates the wallet is full.
place the following code in MultiSigTimelockTest.t.sol:
renounceRole to disable it for all users.The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.
The contest is complete and the rewards are being distributed.