diff options
Diffstat (limited to 'contracts/multisig/contracts/src/MultiSigWalletWithTimeLock.sol')
-rw-r--r-- | contracts/multisig/contracts/src/MultiSigWalletWithTimeLock.sol | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/contracts/multisig/contracts/src/MultiSigWalletWithTimeLock.sol b/contracts/multisig/contracts/src/MultiSigWalletWithTimeLock.sol new file mode 100644 index 000000000..9513d3b30 --- /dev/null +++ b/contracts/multisig/contracts/src/MultiSigWalletWithTimeLock.sol @@ -0,0 +1,127 @@ +/* + + Copyright 2018 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity 0.4.24; + +import "./MultiSigWallet.sol"; + + +/// @title Multisignature wallet with time lock- Allows multiple parties to execute a transaction after a time lock has passed. +/// @author Amir Bandeali - <amir@0xProject.com> +// solhint-disable not-rely-on-time +contract MultiSigWalletWithTimeLock is + MultiSigWallet +{ + event ConfirmationTimeSet(uint256 indexed transactionId, uint256 confirmationTime); + event TimeLockChange(uint256 secondsTimeLocked); + + uint256 public secondsTimeLocked; + + mapping (uint256 => uint256) public confirmationTimes; + + modifier notFullyConfirmed(uint256 transactionId) { + require( + !isConfirmed(transactionId), + "TX_FULLY_CONFIRMED" + ); + _; + } + + modifier fullyConfirmed(uint256 transactionId) { + require( + isConfirmed(transactionId), + "TX_NOT_FULLY_CONFIRMED" + ); + _; + } + + modifier pastTimeLock(uint256 transactionId) { + require( + block.timestamp >= confirmationTimes[transactionId] + secondsTimeLocked, + "TIME_LOCK_INCOMPLETE" + ); + _; + } + + /// @dev Contract constructor sets initial owners, required number of confirmations, and time lock. + /// @param _owners List of initial owners. + /// @param _required Number of required confirmations. + /// @param _secondsTimeLocked Duration needed after a transaction is confirmed and before it becomes executable, in seconds. + constructor ( + address[] _owners, + uint256 _required, + uint256 _secondsTimeLocked + ) + public + MultiSigWallet(_owners, _required) + { + secondsTimeLocked = _secondsTimeLocked; + } + + /// @dev Changes the duration of the time lock for transactions. + /// @param _secondsTimeLocked Duration needed after a transaction is confirmed and before it becomes executable, in seconds. + function changeTimeLock(uint256 _secondsTimeLocked) + public + onlyWallet + { + secondsTimeLocked = _secondsTimeLocked; + emit TimeLockChange(_secondsTimeLocked); + } + + /// @dev Allows an owner to confirm a transaction. + /// @param transactionId Transaction ID. + function confirmTransaction(uint256 transactionId) + public + ownerExists(msg.sender) + transactionExists(transactionId) + notConfirmed(transactionId, msg.sender) + notFullyConfirmed(transactionId) + { + confirmations[transactionId][msg.sender] = true; + emit Confirmation(msg.sender, transactionId); + if (isConfirmed(transactionId)) { + setConfirmationTime(transactionId, block.timestamp); + } + } + + /// @dev Allows anyone to execute a confirmed transaction. + /// @param transactionId Transaction ID. + function executeTransaction(uint256 transactionId) + public + 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; + } + } + + /// @dev Sets the time of when a submission first passed. + function setConfirmationTime(uint256 transactionId, uint256 confirmationTime) + internal + { + confirmationTimes[transactionId] = confirmationTime; + emit ConfirmationTimeSet(transactionId, confirmationTime); + } +} |