-
Notifications
You must be signed in to change notification settings - Fork 0
/
multisig.sol
122 lines (102 loc) · 3.75 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
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
error invalidRequiredMembers();
error ownerAddressCantBeZero();
error duplicateAddressesDetected();
error requiredNumberOfApprovalNotfulfilled();
error insufficientFunds();
error invalidAddress();
error transactionAlreadyExecuted();
error youHaveAlreadyApprovedThisTransaction();
error insufficientApprovals();
contract multisig {
event _deposit(address indexed sender, uint indexed amount);
event _submit(address indexed receiver, address indexed sender, uint indexed amount);
event _approved(address indexed owner, uint indexed txId);
address[] public owners;
uint count;
uint256 public requiredForApproval;
mapping(address=> bool ) public exists;
mapping(uint => bool) isTransactionLive;
mapping(address=>mapping(uint=>bool)) hasOwnerApproved;
mapping(uint => transaction) public transactionById;
struct transaction {
uint txId;
address to;
uint amount;
address sender;
uint currentApprovals;
bool status;
}
modifier onlyOwner{
require(exists[msg.sender]==true,"Youre not owner");
_;
}
modifier checkIfTransactionisLive( uint txId){
require(transactionById[txId].status==false,"transactionAlreadySent");
_;
}
constructor (address[] memory _owners, uint256 _requiredForApproval){
if(_requiredForApproval<1 || _requiredForApproval >_owners.length){
revert invalidRequiredMembers();
}
for(uint8 i = 0; i<_owners.length; i++){
if(address(_owners[i]) == address(0) ) {
revert ownerAddressCantBeZero();
}
else if(exists[_owners[i]]==true){
revert duplicateAddressesDetected();
}
owners.push(_owners[i]);
exists[_owners[i]]=true;
}
requiredForApproval=_requiredForApproval;
}
function deposit() public payable {
emit _deposit(msg.sender,msg.value);
}
function sendTransaction(uint txId) public onlyOwner {
if(transactionById[txId].currentApprovals < requiredForApproval){
revert insufficientApprovals();
}
transactionById[txId].status=true;
payable(transactionById[txId].to).transfer(transactionById[txId].amount);
}
function submitTransaction(address _to, uint _amount) public onlyOwner{
uint amount = _amount *1 ether;
if(address(this).balance<amount){
revert insufficientFunds();
}
if(_to == address(0)){
revert invalidAddress();
}
count++;
transaction memory a = transaction(
count,
_to,
amount,
msg.sender,
0,
false
);
// Transactions.push(a);
transactionById[count]=a;
emit _submit(_to, msg.sender, amount);
}
function approveTransaction(uint txId) public onlyOwner checkIfTransactionisLive(txId) {
if(hasOwnerApproved[msg.sender][txId]==true){
revert youHaveAlreadyApprovedThisTransaction();
}
hasOwnerApproved[msg.sender][txId]=true;
transactionById[txId].currentApprovals++;
emit _approved(msg.sender, txId);
}
function revokeApproval(uint txId) public onlyOwner checkIfTransactionisLive(txId){
require(hasOwnerApproved[msg.sender][txId]==true,"You havent approved this transaction");
hasOwnerApproved[msg.sender][txId]=false;
transactionById[txId].currentApprovals--;
}
function getTotalTransactions() public view returns(uint ){
return count;
}
}