Solidity(七)多签钱包合约程序wallet
单签钱包:只由一个私钥或者助记词来管理、由一个人管理钱包私钥的方式;执行持有对应的私钥就能控制该钱包中的资金;包括收款、转账、提现等交易操作;
单签钱包的优点是方便管理;单签钱包的缺点是一旦私钥被盗,将面临资金全部丢失的风险;
1 简单的单签钱包合约
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
|
pragma solidity >=0.8.2 <0.9;
contract EtherWallet { address payable public owner;
event TransferEvent(address from, address to, uint256 amount);
constructor() { owner = payable(msg.sender); }
receive() external payable { }
modifier onlyOwner() { require(msg.sender == owner, "wallet: caller is not owner"); _; }
function withdraw(uint256 amount) external onlyOwner{ payable (msg.sender).transfer(amount); }
function transfer(address payable to, uint256 amount) public onlyOwner { require(owner.balance >= amount, "wallet: balance not enough"); (bool succeed, ) = to.call{value: amount}(""); require(succeed, "wallet: transfer failed"); emit TransferEvent(owner, to, amount); }
function getBalance() external view returns (uint256) { return address(this).balance; } }
|
2 多签钱包合约
所谓多签钱包,是指设定多个人共同来管理一个地址;必须满足一定数量的管理者签名同意之后才能动用地址账户内的资金;大大降低了资产被盗取的风险;
多签钱包的最大特点是:需要有多个私钥所有者的授权才能执行钱包的交易操作;与单签钱包相比多签钱包在使用和操作上多了授权和撤销两个操作;因为多签钱包机制是由多个用户共同管理一份资产;
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
|
pragma solidity >=0.8.2 <0.9;
contract MultiSignWallet { event Deposit(address indexed sender, uint256 amount); event Submit(uint256 indexed txId); event Approve(address indexed owner, uint256 indexed txId); event Revoke(address indexed owner, uint256 txId); event Execute(uint256 indexed txId);
address[] public owners;
mapping (address => bool) public isOwner; uint public required;
struct Transaction { address to; uint256 value; bytes data; bool executed; }
Transaction[] public transactions; mapping (uint => mapping (address => bool)) public approved;
constructor (address[] memory _owners, uint256 _required) { require(_owners.length > 0, "wallet: owners is required"); require(_required > 0 && _required <= _owners.length, "wallet: invalid require number of owners");
for (uint256 i = 0; i < _owners.length; i ++) { address _owner = _owners[i]; require(_owner != address(0), "wallet: invalid owner"); require(!isOwner[_owner], "wallet: owner had");
isOwner[_owner] = true; owners.push(_owner); } required = _required; }
receive() external payable { emit Deposit(msg.sender, msg.value); }
modifier onlyOwner() { require(isOwner[msg.sender], "wallet: invalid is owner"); _; }
modifier isTxId(uint _txId) { require(_txId < transactions.length, "wallet: invalid txId"); _; }
modifier notApproved(uint _txId) { require(!approved[_txId][msg.sender], "wallet: had approved"); _; }
modifier notExecuted(uint _txId) { require(!transactions[_txId].executed, "wallet: had executed"); _; } function submitTransaction(address _to, uint256 _value, bytes calldata _data) external onlyOwner { transactions.push(Transaction({to: _to, value: _value, data: _data, executed: false})); emit Submit(transactions.length - 1); }
function approve(uint _txId) external onlyOwner isTxId(_txId) notApproved(_txId) notExecuted(_txId) { approved[_txId][msg.sender] = true; emit Approve(msg.sender, _txId); }
function getApproveCount(uint _txId) private view returns (uint256){ uint256 count = 0; for (uint256 i = 0; i < owners.length; i ++) { address owner = owners[i]; if (approved[_txId][owner]) { count ++; } } return count; }
function execute(uint _txId) external isTxId(_txId) notExecuted(_txId) { require(getApproveCount(_txId) >= required, "wallet: approveCount < required");
Transaction storage transaction = transactions[_txId]; transaction.executed = true; (bool successed,) = transaction.to.call{value: transaction.value}(transaction.data); require(successed, "wallet: execute failed"); emit Execute(_txId); }
function revoke(uint _txId) external onlyOwner isTxId(_txId) notExecuted(_txId) { require(approved[_txId][msg.sender], "wallet: not approved"); approved[_txId][msg.sender] = false; emit Revoke(msg.sender, _txId); } }
|