-
Notifications
You must be signed in to change notification settings - Fork 0
/
Wallet.sol
86 lines (73 loc) · 2.52 KB
/
Wallet.sol
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
/**
* A lightweight multisig wallet contract
* Calls will be delegated to the wallet library contract
* Owners can:
* - Submit a transaction
* - Approve and revoke approval of pending transactions
* - Anyone can execute a transaction after enough owners approved it
*/
contract Wallet {
address public walletLibrary;
address[] public owners;
mapping(address => bool) public isOwner;
uint256 public numConfirmationsRequired;
struct Transaction {
address to;
uint256 value;
bytes data;
bool executed;
uint256 numConfirmations;
}
// mapping from tx index => owner => bool
mapping(uint256 => mapping(address => bool)) public isConfirmed;
Transaction[] public transactions;
constructor(
address _walletLibrary,
address[] memory _owners,
uint256 _numConfirmationsRequired
) {
walletLibrary = _walletLibrary;
(bool success, ) = _walletLibrary.delegatecall(
abi.encodeWithSignature(
"initWallet(address[],uint256)",
_owners,
_numConfirmationsRequired
)
);
require(success, "initWallet failed");
}
receive() external payable {}
fallback() external payable {
_delegate(walletLibrary);
}
function _delegate(address _imp) internal virtual {
assembly {
// calldatacopy(t, f, s)
// copy s bytes from calldata at position f to mem at position t
calldatacopy(0, 0, calldatasize())
// delegatecall(g, a, in, insize, out, outsize)
// - call contract at address a
// - with input mem[in…(in+insize))
// - providing g gas
// - and output area mem[out…(out+outsize))
// - returning 0 on error and 1 on success
let result := delegatecall(gas(), _imp, 0, calldatasize(), 0, 0)
// returndatacopy(t, f, s)
// copy s bytes from returndata at position f to mem at position t
returndatacopy(0, 0, returndatasize())
switch result
case 0 {
// revert(p, s)
// end execution, revert state changes, return data mem[p…(p+s))
revert(0, returndatasize())
}
default {
// return(p, s)
// end execution, return data mem[p…(p+s))
return(0, returndatasize())
}
}
}
}