Last active
March 9, 2022 01:50
-
-
Save z0r0z/d9d3538b3530e761905bc5261790d056 to your computer and use it in GitHub Desktop.
Simple gas-optimized multi-signature contract.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: GPL-3.0-or-later | |
pragma solidity >=0.8.4; | |
/// @notice Simple gas-optimized multi-signature contract. | |
contract Multisig { | |
event Propose(address indexed proposer, uint256 indexed proposal); | |
event Sign(address indexed signer, uint256 indexed proposal); | |
event Execute(uint256 indexed proposal); | |
error NotSigner(); | |
error Signed(); | |
error InsufficientSigs(); | |
error ExecuteFailed(); | |
uint256 sigsRequired; | |
uint256 proposalCounter; | |
mapping(address => bool) public signer; | |
mapping(uint256 => Proposal) public proposals; | |
mapping(uint256 => mapping(address => bool)) public signed; | |
struct Proposal { | |
address target; | |
uint256 value; | |
bytes payload; | |
uint256 sigs; | |
} | |
constructor(address[] memory signers_, uint256 sigsRequired_) { | |
// cannot realistically overflow on human timescales | |
unchecked { | |
for (uint256 i; i < signers_.length; i++) { | |
signer[signers_[i]] = true; | |
} | |
} | |
sigsRequired = sigsRequired_; | |
} | |
function propose(address target, uint256 value, bytes calldata payload) external { | |
// cannot realistically overflow on human timescales | |
unchecked { | |
uint256 proposal = proposalCounter++; | |
proposals[proposal] = Proposal({ | |
target: target, | |
value: value, | |
payload: payload, | |
sigs: 0 | |
}); | |
emit Propose(msg.sender, proposal); | |
} | |
} | |
function sign(uint256 proposal) external { | |
if (!signer[msg.sender]) revert NotSigner(); | |
if (signed[proposal][msg.sender]) revert Signed(); | |
// cannot realistically overflow on human timescales | |
unchecked { | |
proposals[proposal].sigs++; | |
} | |
signed[proposal][msg.sender] = true; | |
emit Sign(msg.sender, proposal); | |
} | |
function execute(uint256 proposal) external returns (bool success, bytes memory result) { | |
Proposal storage prop = proposals[proposal]; | |
if (prop.sigs < sigsRequired) revert InsufficientSigs(); | |
(success, result) = prop.target.call{value: prop.value}(prop.payload); | |
if (!success) revert ExecuteFailed(); | |
delete proposals[proposal]; | |
emit Execute(proposal); | |
} | |
receive() external payable virtual {} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment