-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathSimpleMultiSig.sol
More file actions
50 lines (41 loc) · 1.94 KB
/
SimpleMultiSig.sol
File metadata and controls
50 lines (41 loc) · 1.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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 <= 5 && 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);
require(isOwner[msg.sender]);
// 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 {}
}