-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathMultisig.sol
141 lines (120 loc) · 4.85 KB
/
Multisig.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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract MultiSignWallet {
event Deposit(address indexed sender, uint256 amount, uint256 balance);
event SubmitTransaction(
address indexed owner,
uint256 indexed txIndex,
address indexed to,
uint256 value,
bytes data
);
event ConfirmTransaction(address indexed owner, uint256 indexed txIndex);
event RevokeTransaction(address indexed owner, uint256 indexed txIndex);
event ExecuteTransaction(address indexed owner, uint256 indexed txIndex);
address[] public owners;
mapping(address => bool) public isOwner;
uint256 public numConfirmationsRequired;
struct Transaction {
address to;
uint256 value;
bytes data;
bool executed;
uint256 numConfirmations;
}
mapping(uint256 => mapping(address => bool)) public isConfirmed;
Transaction[] public transactions;
modifier onlyOwner() {
require(isOwner[msg.sender], "Not the owner");
_;
}
modifier txExists(uint256 _txIndex) {
require(_txIndex < transactions.length, "Transaction does not exist");
_;
}
modifier notExecuted(uint256 _txIndex) {
require(!transactions[_txIndex].executed, "Transaction already executed");
_;
}
modifier notConfirmed(uint256 _txIndex) {
require(!isConfirmed[_txIndex][msg.sender], "Transaction already confirmed");
_;
}
constructor(address[] memory _owners, uint256 _numConfirmationsRequired) {
require(_owners.length > 0, "At least one owner required");
require(_numConfirmationsRequired > 0 && _numConfirmationsRequired <= _owners.length, "Invalid number of required confirmations");
for (uint256 i = 0; i < _owners.length; i++) {
address owner = _owners[i];
require(owner != address(0), "Invalid owner");
require(!isOwner[owner], "Owner not unique");
isOwner[owner] = true;
owners.push(owner);
}
numConfirmationsRequired = _numConfirmationsRequired;
}
function confirmTransaction(uint256 _txIndex) public onlyOwner txExists(_txIndex) notExecuted(_txIndex) notConfirmed(_txIndex) {
Transaction storage transaction = transactions[_txIndex];
transaction.numConfirmations += 1;
isConfirmed[_txIndex][msg.sender] = true;
emit ConfirmTransaction(msg.sender, _txIndex);
}
function submitTransaction(address _to, uint256 _value, bytes memory _data) public onlyOwner {
uint256 txIndex = transactions.length;
transactions.push(
Transaction({
to: _to,
value: _value,
data: _data,
executed: false,
numConfirmations: 0
})
);
emit SubmitTransaction(msg.sender, txIndex, _to, _value, _data);
}
function depositETH() public payable {
require(msg.value > 0, "Value must be greater than 0");
emit Deposit(msg.sender, msg.value, address(this).balance);
}
receive() external payable {}
function executeTransaction(uint256 _txIndex) public onlyOwner txExists(_txIndex) notExecuted(_txIndex) {
Transaction storage transaction = transactions[_txIndex];
require(transaction.numConfirmations >= numConfirmationsRequired, "Cannot execute transaction: not enough confirmations");
transaction.executed = true;
(bool success, ) = transaction.to.call{value: transaction.value}(transaction.data);
require(success, "Transaction failed");
emit ExecuteTransaction(msg.sender, _txIndex);
}
function revokeConfirmation(uint256 _txIndex) public onlyOwner txExists(_txIndex) notExecuted(_txIndex) {
Transaction storage transaction = transactions[_txIndex];
require(isConfirmed[_txIndex][msg.sender], "Transaction not confirmed");
transaction.numConfirmations -= 1;
isConfirmed[_txIndex][msg.sender] = false;
emit RevokeTransaction(msg.sender, _txIndex);
}
function getOwners() public view returns (address[] memory) {
return owners;
}
function getTransactionCount() public view returns (uint256) {
return transactions.length;
}
function getTransaction(uint256 _txIndex) public view returns (
address to,
uint256 value,
bytes memory data,
bool executed,
uint256 numConfirmations
) {
Transaction storage transaction = transactions[_txIndex];
return (
transaction.to,
transaction.value,
transaction.data,
transaction.executed,
transaction.numConfirmations
);
}
function getBalance() public view returns (uint256) {
return address(this).balance;
}
}
//0x762f61e913443c792d0af627e2501d885b156357f2a9c777de8c3e8747a8792f