-
Notifications
You must be signed in to change notification settings - Fork 1
/
MultiSig_Ownership.sol
132 lines (100 loc) · 3.58 KB
/
MultiSig_Ownership.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
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MultiSigWallet {
uint256 public requiredSigners;
address public mainAdmin;
mapping(address => bool) public isSigner;
struct Transaction {
address destination;
uint256 value;
bytes data;
bool executed;
uint256 signedBy;
}
Transaction[] public transactions;
mapping(address => mapping(uint256 => bool)) public userSignedTransaction;
constructor(address _mainAdmin, address[] memory signers){
_addSigner(_mainAdmin);
for(uint256 i = 0; i < signers.length;){
_addSigner(signers[i]);
unchecked {
++i;
}
}
}
modifier onlySigner() {
require(_isSigner(msg.sender), "Not a signer");
_;
}
modifier onlyMainAdmin() {
require(msg.sender == mainAdmin, "Not main admin");
_;
}
function submitTransaction(address destination, uint256 value, bytes memory data) external onlySigner {
userSignedTransaction[msg.sender][transactions.length] = true;
transactions.push(Transaction({
destination: destination,
value: value,
data: data,
executed: false,
signedBy: 1
}));
}
function signTransaction(uint256 txId) external onlySigner {
Transaction storage transaction = transactions[txId];
require(!transaction.executed, "Already executed");
require(!userSignedTransaction[msg.sender][txId], "You already signed!");
userSignedTransaction[msg.sender][txId] = true;
transaction.signedBy++;
if(transaction.signedBy == requiredSigners){
_executeTransaction(txId);
}
}
function addSigners(address[] memory signers) external onlyMainAdmin {
for(uint256 i = 0; i < signers.length;){
_addSigner(signers[i]);
unchecked {
++i;
}
}
}
function removeSigners(address[] memory signers) external onlyMainAdmin {
for(uint256 i = 0; i < signers.length;){
_removeSigners(signers[i]);
unchecked {
++i;
}
}
}
function _executeTransaction(uint256 _txId) internal {
Transaction storage transaction = transactions[_txId];
transaction.executed = true;
(bool success, ) = transaction.destination.call{value: transaction.value}(transaction.data);
require(success, "Transaction failed");
_removeTransaction(_txId);
}
function _addSigner(address _who) internal {
require(!isSigner[_who], "Already a signer");
isSigner[_who] = true;
requiredSigners++;
}
function _removeSigners(address _who) internal {
require(isSigner[_who], "Not a signer");
isSigner[_who] = false;
requiredSigners--;
}
function _removeTransaction(uint256 _txId) internal {
transactions[_txId] = transactions[transactions.length - 1];
transactions.pop();
}
function _isSigner(address _who) internal view returns(bool) {
return isSigner[_who];
}
function getTransactionLenght() external view returns(uint256) {
return transactions.length;
}
function getTransactionDetails(uint256 _txId) external view returns(address, uint256, bytes memory, bool, uint256) {
Transaction storage transaction = transactions[_txId];
return (transaction.destination, transaction.value, transaction.data, transaction.executed, transaction.signedBy);
}
}