编译器
0.6.12+commit.27d51765
文件 1 的 3:MultiSigWallet.sol
pragma solidity ^0.6.12;
contract MultiSigWallet {
event Confirmation(address indexed sender, uint indexed transactionId);
event Revocation(address indexed sender, uint indexed transactionId);
event Submission(uint indexed transactionId);
event Execution(uint indexed transactionId);
event ExecutionFailure(uint indexed transactionId);
event Deposit(address indexed sender, uint value);
event OwnerAddition(address indexed owner);
event OwnerRemoval(address indexed owner);
event RequirementChange(uint required);
uint constant public MAX_OWNER_COUNT = 50;
mapping (uint => Transaction) public transactions;
mapping (uint => mapping (address => bool)) public confirmations;
mapping (address => bool) public isOwner;
address[] public owners;
uint public required;
uint public transactionCount;
struct Transaction {
address destination;
uint value;
bytes data;
bool executed;
}
modifier onlyWallet() {
require(msg.sender == address(this));
_;
}
modifier ownerDoesNotExist(address owner) {
require(!isOwner[owner]);
_;
}
modifier ownerExists(address owner) {
require(isOwner[owner]);
_;
}
modifier transactionExists(uint transactionId) {
require(transactions[transactionId].destination != address(0));
_;
}
modifier confirmed(uint transactionId, address owner) {
require(confirmations[transactionId][owner]);
_;
}
modifier notConfirmed(uint transactionId, address owner) {
require(!confirmations[transactionId][owner]);
_;
}
modifier notExecuted(uint transactionId) {
require(!transactions[transactionId].executed);
_;
}
modifier notNull(address _address) {
require(_address != address(0));
_;
}
modifier validRequirement(uint ownerCount, uint _required) {
require(ownerCount <= MAX_OWNER_COUNT
&& _required <= ownerCount
&& _required != 0
&& ownerCount != 0);
_;
}
fallback()
external
payable
{
if (msg.value > 0)
emit Deposit(msg.sender, msg.value);
}
constructor(address[] memory _owners, uint _required)
public
validRequirement(_owners.length, _required)
{
for (uint i=0; i<_owners.length; i++) {
require(!isOwner[_owners[i]] && _owners[i] != address(0));
isOwner[_owners[i]] = true;
}
owners = _owners;
required = _required;
}
function addOwner(address owner)
public
onlyWallet
ownerDoesNotExist(owner)
notNull(owner)
validRequirement(owners.length + 1, required)
{
isOwner[owner] = true;
owners.push(owner);
emit OwnerAddition(owner);
}
function removeOwner(address owner)
public
onlyWallet
ownerExists(owner)
{
isOwner[owner] = false;
for (uint i=0; i<owners.length - 1; i++)
if (owners[i] == owner) {
owners[i] = owners[owners.length - 1];
break;
}
owners.pop();
if (required > owners.length)
changeRequirement(owners.length);
emit OwnerRemoval(owner);
}
function replaceOwner(address owner, address newOwner)
public
onlyWallet
ownerExists(owner)
ownerDoesNotExist(newOwner)
{
for (uint i=0; i<owners.length; i++)
if (owners[i] == owner) {
owners[i] = newOwner;
break;
}
isOwner[owner] = false;
isOwner[newOwner] = true;
emit OwnerRemoval(owner);
emit OwnerAddition(newOwner);
}
function changeRequirement(uint _required)
public
onlyWallet
validRequirement(owners.length, _required)
{
required = _required;
emit RequirementChange(_required);
}
function submitTransaction(address destination, uint value, bytes memory data)
public
returns (uint transactionId)
{
transactionId = addTransaction(destination, value, data);
confirmTransaction(transactionId);
}
function confirmTransaction(uint transactionId)
public
virtual
ownerExists(msg.sender)
transactionExists(transactionId)
notConfirmed(transactionId, msg.sender)
{
confirmations[transactionId][msg.sender] = true;
emit Confirmation(msg.sender, transactionId);
executeTransaction(transactionId);
}
function revokeConfirmation(uint transactionId)
public
ownerExists(msg.sender)
confirmed(transactionId, msg.sender)
notExecuted(transactionId)
{
confirmations[transactionId][msg.sender] = false;
emit Revocation(msg.sender, transactionId);
}
function executeTransaction(uint transactionId)
public
virtual
ownerExists(msg.sender)
confirmed(transactionId, msg.sender)
notExecuted(transactionId)
{
if (isConfirmed(transactionId)) {
Transaction storage txn = transactions[transactionId];
txn.executed = true;
if (external_call(txn.destination, txn.value, txn.data.length, txn.data))
Execution(transactionId);
else {
ExecutionFailure(transactionId);
txn.executed = false;
}
}
}
function external_call(address destination, uint value, uint dataLength, bytes memory data) internal returns (bool) {
bool result;
assembly {
let x := mload(0x40)
let d := add(data, 32)
result := call(
sub(gas(), 34710),
destination,
value,
d,
dataLength,
x,
0
)
}
return result;
}
function isConfirmed(uint transactionId)
public
view
returns (bool)
{
uint count = 0;
for (uint i=0; i<owners.length; i++) {
if (confirmations[transactionId][owners[i]])
count += 1;
if (count == required)
return true;
}
}
function addTransaction(address destination, uint value, bytes memory data)
internal
notNull(destination)
returns (uint transactionId)
{
transactionId = transactionCount;
transactions[transactionId] = Transaction({
destination: destination,
value: value,
data: data,
executed: false
});
transactionCount += 1;
Submission(transactionId);
}
function getConfirmationCount(uint transactionId)
public
view
returns (uint count)
{
for (uint i=0; i<owners.length; i++)
if (confirmations[transactionId][owners[i]])
count += 1;
}
function getTransactionCount(bool pending, bool executed)
public
view
returns (uint count)
{
for (uint i=0; i<transactionCount; i++)
if ( pending && !transactions[i].executed
|| executed && transactions[i].executed)
count += 1;
}
function getOwners()
public
view
returns (address[] memory)
{
return owners;
}
function getConfirmations(uint transactionId)
public
view
returns (address[] memory _confirmations)
{
address[] memory confirmationsTemp = new address[](owners.length);
uint count = 0;
uint i;
for (i=0; i<owners.length; i++)
if (confirmations[transactionId][owners[i]]) {
confirmationsTemp[count] = owners[i];
count += 1;
}
_confirmations = new address[](count);
for (i=0; i<count; i++)
_confirmations[i] = confirmationsTemp[i];
}
function getTransactionIds(uint from, uint to, bool pending, bool executed)
public
view
returns (uint[] memory _transactionIds)
{
uint[] memory transactionIdsTemp = new uint[](transactionCount);
uint count = 0;
uint i;
for (i=0; i<transactionCount; i++)
if ( pending && !transactions[i].executed
|| executed && transactions[i].executed)
{
transactionIdsTemp[count] = i;
count += 1;
}
_transactionIds = new uint[](to - from);
for (i=from; i<to; i++)
_transactionIds[i - from] = transactionIdsTemp[i];
}
}
文件 2 的 3:MultiSigWalletWithTimelock.sol
pragma solidity ^0.6.12;
import "@openzeppelin/contracts/math/SafeMath.sol";
import "./MultiSigWallet.sol";
contract MultiSigWalletWithTimeLock is
MultiSigWallet
{
using SafeMath for uint256;
event ConfirmationTimeSet(uint256 indexed transactionId, uint256 confirmationTime);
event TimeLockChange(uint256 secondsTimeLocked);
uint256 public secondsTimeLocked;
mapping (uint256 => uint256) public confirmationTimes;
modifier fullyConfirmed(uint256 transactionId) {
require(
isConfirmed(transactionId),
"TX_NOT_FULLY_CONFIRMED"
);
_;
}
modifier pastTimeLock(uint256 transactionId) {
require(
block.timestamp >= confirmationTimes[transactionId].add(secondsTimeLocked),
"TIME_LOCK_INCOMPLETE"
);
_;
}
constructor (
address[] memory _owners,
uint256 _required,
uint256 _secondsTimeLocked
)
public
MultiSigWallet(_owners, _required)
{
secondsTimeLocked = _secondsTimeLocked;
}
function changeTimeLock(uint256 _secondsTimeLocked)
public
onlyWallet
{
secondsTimeLocked = _secondsTimeLocked;
emit TimeLockChange(_secondsTimeLocked);
}
function confirmTransaction(uint256 transactionId)
public
override
ownerExists(msg.sender)
transactionExists(transactionId)
notConfirmed(transactionId, msg.sender)
{
bool isTxFullyConfirmedBeforeConfirmation = isConfirmed(transactionId);
confirmations[transactionId][msg.sender] = true;
emit Confirmation(msg.sender, transactionId);
if (!isTxFullyConfirmedBeforeConfirmation && isConfirmed(transactionId)) {
_setConfirmationTime(transactionId, block.timestamp);
}
}
function executeTransaction(uint256 transactionId)
public
override
notExecuted(transactionId)
fullyConfirmed(transactionId)
pastTimeLock(transactionId)
{
Transaction storage txn = transactions[transactionId];
txn.executed = true;
if (external_call(txn.destination, txn.value, txn.data.length, txn.data)) {
emit Execution(transactionId);
} else {
emit ExecutionFailure(transactionId);
txn.executed = false;
}
}
function _setConfirmationTime(uint256 transactionId, uint256 confirmationTime)
internal
{
confirmationTimes[transactionId] = confirmationTime;
emit ConfirmationTimeSet(transactionId, confirmationTime);
}
}
文件 3 的 3:SafeMath.sol
pragma solidity ^0.6.0;
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
{
"compilationTarget": {
"contracts/MultiSigWalletWithTimelock.sol": "MultiSigWalletWithTimeLock"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 999999
},
"remappings": []
}
[{"inputs":[{"internalType":"address[]","name":"_owners","type":"address[]"},{"internalType":"uint256","name":"_required","type":"uint256"},{"internalType":"uint256","name":"_secondsTimeLocked","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"uint256","name":"transactionId","type":"uint256"}],"name":"Confirmation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"transactionId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"confirmationTime","type":"uint256"}],"name":"ConfirmationTimeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"transactionId","type":"uint256"}],"name":"Execution","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"transactionId","type":"uint256"}],"name":"ExecutionFailure","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"OwnerAddition","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"OwnerRemoval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"required","type":"uint256"}],"name":"RequirementChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"uint256","name":"transactionId","type":"uint256"}],"name":"Revocation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"transactionId","type":"uint256"}],"name":"Submission","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"secondsTimeLocked","type":"uint256"}],"name":"TimeLockChange","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"MAX_OWNER_COUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"addOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_required","type":"uint256"}],"name":"changeRequirement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_secondsTimeLocked","type":"uint256"}],"name":"changeTimeLock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"transactionId","type":"uint256"}],"name":"confirmTransaction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"confirmationTimes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"confirmations","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"transactionId","type":"uint256"}],"name":"executeTransaction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"transactionId","type":"uint256"}],"name":"getConfirmationCount","outputs":[{"internalType":"uint256","name":"count","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"transactionId","type":"uint256"}],"name":"getConfirmations","outputs":[{"internalType":"address[]","name":"_confirmations","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOwners","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"pending","type":"bool"},{"internalType":"bool","name":"executed","type":"bool"}],"name":"getTransactionCount","outputs":[{"internalType":"uint256","name":"count","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"from","type":"uint256"},{"internalType":"uint256","name":"to","type":"uint256"},{"internalType":"bool","name":"pending","type":"bool"},{"internalType":"bool","name":"executed","type":"bool"}],"name":"getTransactionIds","outputs":[{"internalType":"uint256[]","name":"_transactionIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"transactionId","type":"uint256"}],"name":"isConfirmed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"owners","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"removeOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"newOwner","type":"address"}],"name":"replaceOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"required","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"transactionId","type":"uint256"}],"name":"revokeConfirmation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"secondsTimeLocked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"destination","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"submitTransaction","outputs":[{"internalType":"uint256","name":"transactionId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"transactionCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"transactions","outputs":[{"internalType":"address","name":"destination","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bool","name":"executed","type":"bool"}],"stateMutability":"view","type":"function"}]