MultiSig Timelock

First Flight #55
Beginner FriendlyWallet
100 EXP
Submission Details
Impact: low
Likelihood: low

No Event Emission for Signer Role Changes in Constructor

Author Revealed upon completion

Description

  • The constructor grants the SIGNING_ROLE to the deployer using _grantRole(), which does emit a RoleGranted event from OpenZeppelin's AccessControl.

  • However, for consistency and better off-chain monitoring, explicit event emission for the initial signer setup would improve transparency and make it easier to track the contract's initialization.

constructor() Ownable(msg.sender) {
// Automatically add deployer as first signer
s_signers[0] = msg.sender;
s_isSigner[msg.sender] = true;
s_signerCount = 1;
@> // Grant signing role to deployer
@> _grantRole(SIGNING_ROLE, msg.sender); // Emits RoleGranted but no custom event
}

Risk

Likelihood:

  • The contract is deployed and the deployer is set as the first signer without any custom event emission

  • Off-chain systems monitoring the contract might miss the initial signer setup in their indexing

Impact:

  • Reduced transparency for initial contract state

  • Off-chain monitoring systems might have incomplete data about the initial signer

  • Minor inconsistency compared to how subsequent signers are added (which emit RoleGranted events)

Proof of Concept

function testConstructorNoCustomEventEmission() public {
// Deploy new contract
MultiSigTimelock newMultiSig = new MultiSigTimelock();
// Constructor sets deployer as signer but no custom event emitted
// Only RoleGranted from OpenZeppelin is emitted
// This is inconsistent with grantSigningRole which would emit RoleGranted
}

Recommended Mitigation

+ event InitialSignerSet(address indexed initialSigner);
constructor() Ownable(msg.sender) {
// Automatically add deployer as first signer
s_signers[0] = msg.sender;
s_isSigner[msg.sender] = true;
s_signerCount = 1;
// Grant signing role to deployer
_grantRole(SIGNING_ROLE, msg.sender);
+ emit InitialSignerSet(msg.sender);
}

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!