Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.4.24+commit.e67f0147.js&optimize=false&gist=
pragma solidity ^0.4.22; | |
contract SimpleMultiSig { | |
uint public nonce; // (only) mutable state | |
uint public threshold; // immutable state | |
mapping (address => bool) isOwner; // immutable state | |
address[] public ownersArr; // immutable state | |
// Note that owners_ must be strictly increasing, in order to prevent duplicates | |
constructor(uint threshold_, address[] owners_) public { | |
require(owners_.length <= 10 && threshold_ <= owners_.length && threshold_ >= 0); | |
address lastAdd = address(0); | |
for (uint i = 0; i < owners_.length; i++) { | |
require(owners_[i] > lastAdd); | |
isOwner[owners_[i]] = true; | |
lastAdd = owners_[i]; | |
} | |
ownersArr = owners_; | |
threshold = threshold_; | |
} | |
// Note that address recovered from signatures must be strictly increasing, in order to prevent duplicates | |
function execute(uint8[] sigV, bytes32[] sigR, bytes32[] sigS, address destination, uint value, bytes data) public { | |
require(sigR.length == threshold); | |
require(sigR.length == sigS.length && sigR.length == sigV.length); | |
// Follows ERC191 signature scheme: https://github.com/ethereum/EIPs/issues/191 | |
bytes32 txHash = keccak256(abi.encodePacked(byte(0x19), byte(0), this, destination, value, data, nonce)); | |
address lastAdd = address(0); // cannot have address(0) as an owner | |
for (uint i = 0; i < threshold; i++) { | |
address recovered = ecrecover(txHash, sigV[i], sigR[i], sigS[i]); | |
require(recovered > lastAdd && isOwner[recovered]); | |
lastAdd = recovered; | |
} | |
// If we make it here all signatures are accounted for. | |
// The address.call() syntax is no longer recommended, see: | |
// https://github.com/ethereum/solidity/issues/2884 | |
nonce = nonce + 1; | |
bool success = false; | |
assembly { success := call(gas, destination, value, add(data, 0x20), mload(data), 0, 0) } | |
require(success); | |
} | |
function () payable public {} | |
} |
pragma solidity ^0.4.18; | |
// This contract is only used for testing purposes. | |
contract TestRegistry { | |
mapping(address => uint) public registry; | |
function register(uint x) payable public { | |
registry[msg.sender] = x; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment