Skip to content
This repository has been archived by the owner on Aug 24, 2021. It is now read-only.

Experimental Feature #334

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 112 additions & 0 deletions contracts/MultiSigWalletWithExternalDailyLimit
Original file line number Diff line number Diff line change
@@ -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 - <[email protected]>
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;
}
}