2018-10-24 12:52:11 +00:00
|
|
|
pragma solidity >=0.0;
|
2017-07-05 10:28:15 +00:00
|
|
|
import "MultiSigWallet.sol";
|
|
|
|
|
|
|
|
|
|
|
|
/// @title Multisignature wallet with daily limit - Allows an owner to withdraw a daily limit without multisig.
|
|
|
|
/// @author Stefan George - <stefan.george@consensys.net>
|
|
|
|
contract MultiSigWalletWithDailyLimit is MultiSigWallet {
|
|
|
|
|
|
|
|
event DailyLimitChange(uint dailyLimit);
|
|
|
|
|
|
|
|
uint public dailyLimit;
|
|
|
|
uint public lastDay;
|
|
|
|
uint public spentToday;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Public functions
|
|
|
|
*/
|
|
|
|
/// @dev Contract constructor sets initial owners, required number of confirmations and daily withdraw limit.
|
|
|
|
/// @param _owners List of initial owners.
|
|
|
|
/// @param _required Number of required confirmations.
|
|
|
|
/// @param _dailyLimit Amount in wei, which can be withdrawn without confirmations on a daily basis.
|
2018-07-14 21:42:01 +00:00
|
|
|
constructor(address[] memory _owners, uint _required, uint _dailyLimit)
|
2017-07-05 10:28:15 +00:00
|
|
|
MultiSigWallet(_owners, _required)
|
|
|
|
{
|
|
|
|
dailyLimit = _dailyLimit;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// @dev Allows to change the daily limit. Transaction has to be sent by wallet.
|
|
|
|
/// @param _dailyLimit Amount in wei.
|
|
|
|
function changeDailyLimit(uint _dailyLimit)
|
|
|
|
public
|
|
|
|
onlyWallet
|
|
|
|
{
|
|
|
|
dailyLimit = _dailyLimit;
|
2018-06-27 08:35:38 +00:00
|
|
|
emit DailyLimitChange(_dailyLimit);
|
2017-07-05 10:28:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// @dev Allows anyone to execute a confirmed transaction or ether withdraws until daily limit is reached.
|
|
|
|
/// @param transactionId Transaction ID.
|
|
|
|
function executeTransaction(uint transactionId)
|
|
|
|
public
|
2019-09-16 12:33:43 +00:00
|
|
|
override
|
2017-07-05 10:28:15 +00:00
|
|
|
notExecuted(transactionId)
|
|
|
|
{
|
2018-07-11 11:30:46 +00:00
|
|
|
Transaction storage tx = transactions[transactionId];
|
2017-07-05 10:28:15 +00:00
|
|
|
bool confirmed = isConfirmed(transactionId);
|
|
|
|
if (confirmed || tx.data.length == 0 && isUnderLimit(tx.value)) {
|
|
|
|
if (!confirmed)
|
|
|
|
spentToday += tx.value;
|
2020-04-03 14:29:17 +00:00
|
|
|
(tx.executed,) = tx.destination.call{value: tx.value}(tx.data);
|
2018-08-15 22:39:19 +00:00
|
|
|
if (tx.executed)
|
2018-06-27 08:35:38 +00:00
|
|
|
emit Execution(transactionId);
|
2017-07-05 10:28:15 +00:00
|
|
|
else {
|
2018-06-27 08:35:38 +00:00
|
|
|
emit ExecutionFailure(transactionId);
|
2017-07-05 10:28:15 +00:00
|
|
|
if (!confirmed)
|
|
|
|
spentToday -= tx.value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Internal functions
|
|
|
|
*/
|
|
|
|
/// @dev Returns if amount is within daily limit and resets spentToday after one day.
|
|
|
|
/// @param amount Amount to withdraw.
|
|
|
|
/// @return Returns if amount is under daily limit.
|
|
|
|
function isUnderLimit(uint amount)
|
|
|
|
internal
|
|
|
|
returns (bool)
|
|
|
|
{
|
2020-05-05 08:56:31 +00:00
|
|
|
if (block.timestamp > lastDay + 24 hours) {
|
|
|
|
lastDay = block.timestamp;
|
2017-07-05 10:28:15 +00:00
|
|
|
spentToday = 0;
|
|
|
|
}
|
|
|
|
if (spentToday + amount > dailyLimit || spentToday + amount < spentToday)
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Web3 call functions
|
|
|
|
*/
|
|
|
|
/// @dev Returns maximum withdraw amount.
|
|
|
|
/// @return Returns amount.
|
|
|
|
function calcMaxWithdraw()
|
|
|
|
public
|
2018-07-02 09:14:28 +00:00
|
|
|
view
|
2017-07-05 10:28:15 +00:00
|
|
|
returns (uint)
|
|
|
|
{
|
2020-05-05 08:56:31 +00:00
|
|
|
if (block.timestamp > lastDay + 24 hours)
|
2017-07-05 10:28:15 +00:00
|
|
|
return dailyLimit;
|
|
|
|
if (dailyLimit < spentToday)
|
|
|
|
return 0;
|
|
|
|
return dailyLimit - spentToday;
|
|
|
|
}
|
|
|
|
}
|