From 88f1606bd2ac88ac84dbdde001cd038c3cb2d272 Mon Sep 17 00:00:00 2001 From: Dean Eigenmann Date: Fri, 24 Jan 2020 05:08:08 +0100 Subject: [PATCH] Create MultiSigWalletWithExternalDailyLimit --- .../MultiSigWalletWithExternalDailyLimit | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 contracts/MultiSigWalletWithExternalDailyLimit diff --git a/contracts/MultiSigWalletWithExternalDailyLimit b/contracts/MultiSigWalletWithExternalDailyLimit new file mode 100644 index 00000000..2cdda59a --- /dev/null +++ b/contracts/MultiSigWalletWithExternalDailyLimit @@ -0,0 +1,112 @@ +pragma solidity ^0.4.15; +import "./MultiSigWallet.sol"; + +interface DailyLimit { + + function limit() returns (uint256); + +} + + +/// @title Multisignature wallet with daily limit - Allows an owner to withdraw a daily limit without multisig. +/// @author Stefan George - +contract MultiSigWalletWithExternalDailyLimit is MultiSigWallet { + + /* + * Events + */ + event DailyLimitChange(DailyLimit dailyLimit); + + /* + * Storage + */ + DailyLimit 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 An external address providing the daily limit. + function MultiSigWalletWithDailyLimit(address[] _owners, uint _required, DailyLimit _dailyLimit) + public + 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(DailyLimit _dailyLimit) + public + onlyWallet + { + dailyLimit = _dailyLimit; + DailyLimitChange(_dailyLimit); + } + + /// @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 + ownerExists(msg.sender) + confirmed(transactionId, msg.sender) + notExecuted(transactionId) + { + Transaction storage txn = transactions[transactionId]; + bool _confirmed = isConfirmed(transactionId); + if (_confirmed || txn.data.length == 0 && isUnderLimit(txn.value)) { + txn.executed = true; + if (!_confirmed) + spentToday += txn.value; + if (external_call(txn.destination, txn.value, txn.data.length, txn.data)) + Execution(transactionId); + else { + ExecutionFailure(transactionId); + txn.executed = false; + if (!_confirmed) + spentToday -= txn.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) + { + if (now > lastDay + 24 hours) { + lastDay = now; + spentToday = 0; + } + if (spentToday + amount > dailyLimit.limit() || spentToday + amount < spentToday) + return false; + return true; + } + + /* + * Web3 call functions + */ + /// @dev Returns maximum withdraw amount. + /// @return Returns amount. + function calcMaxWithdraw() + public + constant + returns (uint) + { + limit = dailyLimit.limit(); + if (now > lastDay + 24 hours) + return limit; + if (limit < spentToday) + return 0; + return limit - spentToday; + } +}