ETH Price: $2,025.89 (-1.35%)

Transaction Decoder

Block:
4390095 at Oct-19-2017 03:05:44 PM +UTC
Transaction Fee:
0.001306998 ETH $2.65
Gas Used:
62,238 Gas / 21 Gwei

Emitted Events:

2 MultiSigWalletWithDailyLimit.Deposit( sender=[Receiver] DutchAuction, value=2490000000000000000 )
3 DutchAuction.BidSubmission( _sender=[Sender] 0x75f9e9aebe0447280037eba7a405145227916457, _amount=2490000000000000000, _missing_funds=18104020778211770418029246 )

Account State Difference:

  Address   Before After State Difference Code
0x00C71226...11E97561e
(Raiden: MultiSig)
14,767.923265731981970754 Eth14,770.413265731981970754 Eth2.49
(Spark Pool)
758.255114874826007951 Eth758.256421872826007951 Eth0.001306998
0x75f9E9AE...227916457
3.43771537 Eth
Nonce: 0
0.946408372 Eth
Nonce: 1
2.491306998
0xb5E5585D...FB10B5A01
(Raiden: Token Auction)

Execution Trace

ETH 2.49 DutchAuction.CALL( )
  • ETH 2.49 MultiSigWalletWithDailyLimit.CALL( )
    File 1 of 2: DutchAuction
    pragma solidity ^0.4.17;
    
    /// @title ERC223ReceivingContract - Standard contract implementation for compatibility with ERC223 tokens.
    contract ERC223ReceivingContract {
    
        /// @dev Function that is called when a user or another contract wants to transfer funds.
        /// @param _from Transaction initiator, analogue of msg.sender
        /// @param _value Number of tokens to transfer.
        /// @param _data Data containig a function signature and/or parameters
        function tokenFallback(address _from, uint256 _value, bytes _data) public;
    }
    
    contract Token {
        /*
         * Implements ERC 20 standard.
         * https://github.com/ethereum/EIPs/blob/f90864a3d2b2b45c4decf95efd26b3f0c276051a/EIPS/eip-20-token-standard.md
         * https://github.com/ethereum/EIPs/issues/20
         *
         *  Added support for the ERC 223 "tokenFallback" method in a "transfer" function with a payload.
         *  https://github.com/ethereum/EIPs/issues/223
         */
    
        /*
         * This is a slight change to the ERC20 base standard.
         * function totalSupply() constant returns (uint256 supply);
         * is replaced with:
         * uint256 public totalSupply;
         * This automatically creates a getter function for the totalSupply.
         * This is moved to the base contract since public getter functions are not
         * currently recognised as an implementation of the matching abstract
         * function by the compiler.
         */
        uint256 public totalSupply;
    
        /*
         * ERC 20
         */
        function balanceOf(address _owner) public constant returns (uint256 balance);
        function transfer(address _to, uint256 _value) public returns (bool success);
        function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
        function approve(address _spender, uint256 _value) public returns (bool success);
        function allowance(address _owner, address _spender) public constant returns (uint256 remaining);
    
        /*
         * ERC 223
         */
        function transfer(address _to, uint256 _value, bytes _data) public returns (bool success);
    
        /*
         * Events
         */
        event Transfer(address indexed _from, address indexed _to, uint256 _value);
        event Approval(address indexed _owner, address indexed _spender, uint256 _value);
    
        // There is no ERC223 compatible Transfer event, with `_data` included.
    }
    
    
    /// @title Standard token contract - Standard token implementation.
    contract StandardToken is Token {
    
        /*
         * Data structures
         */
        mapping (address => uint256) balances;
        mapping (address => mapping (address => uint256)) allowed;
    
        /*
         * Public functions
         */
        /// @notice Send `_value` tokens to `_to` from `msg.sender`.
        /// @dev Transfers sender's tokens to a given address. Returns success.
        /// @param _to Address of token receiver.
        /// @param _value Number of tokens to transfer.
        /// @return Returns success of function call.
        function transfer(address _to, uint256 _value) public returns (bool) {
            require(_to != 0x0);
            require(_to != address(this));
            require(balances[msg.sender] >= _value);
            require(balances[_to] + _value >= balances[_to]);
    
            balances[msg.sender] -= _value;
            balances[_to] += _value;
    
            Transfer(msg.sender, _to, _value);
    
            return true;
        }
    
        /// @notice Send `_value` tokens to `_to` from `msg.sender` and trigger
        /// tokenFallback if sender is a contract.
        /// @dev Function that is called when a user or another contract wants to transfer funds.
        /// @param _to Address of token receiver.
        /// @param _value Number of tokens to transfer.
        /// @param _data Data to be sent to tokenFallback
        /// @return Returns success of function call.
        function transfer(
            address _to,
            uint256 _value,
            bytes _data)
            public
            returns (bool)
        {
            require(transfer(_to, _value));
    
            uint codeLength;
    
            assembly {
                // Retrieve the size of the code on target address, this needs assembly.
                codeLength := extcodesize(_to)
            }
    
            if (codeLength > 0) {
                ERC223ReceivingContract receiver = ERC223ReceivingContract(_to);
                receiver.tokenFallback(msg.sender, _value, _data);
            }
    
            return true;
        }
    
        /// @notice Transfer `_value` tokens from `_from` to `_to` if `msg.sender` is allowed.
        /// @dev Allows for an approved third party to transfer tokens from one
        /// address to another. Returns success.
        /// @param _from Address from where tokens are withdrawn.
        /// @param _to Address to where tokens are sent.
        /// @param _value Number of tokens to transfer.
        /// @return Returns success of function call.
        function transferFrom(address _from, address _to, uint256 _value)
            public
            returns (bool)
        {
            require(_from != 0x0);
            require(_to != 0x0);
            require(_to != address(this));
            require(balances[_from] >= _value);
            require(allowed[_from][msg.sender] >= _value);
            require(balances[_to] + _value >= balances[_to]);
    
            balances[_to] += _value;
            balances[_from] -= _value;
            allowed[_from][msg.sender] -= _value;
    
            Transfer(_from, _to, _value);
    
            return true;
        }
    
        /// @notice Allows `_spender` to transfer `_value` tokens from `msg.sender` to any address.
        /// @dev Sets approved amount of tokens for spender. Returns success.
        /// @param _spender Address of allowed account.
        /// @param _value Number of approved tokens.
        /// @return Returns success of function call.
        function approve(address _spender, uint256 _value) public returns (bool) {
            require(_spender != 0x0);
    
            // To change the approve amount you first have to reduce the addresses`
            // allowance to zero by calling `approve(_spender, 0)` if it is not
            // already 0 to mitigate the race condition described here:
            // https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
            require(_value == 0 || allowed[msg.sender][_spender] == 0);
    
            allowed[msg.sender][_spender] = _value;
            Approval(msg.sender, _spender, _value);
            return true;
        }
    
        /*
         * Read functions
         */
        /// @dev Returns number of allowed tokens that a spender can transfer on
        /// behalf of a token owner.
        /// @param _owner Address of token owner.
        /// @param _spender Address of token spender.
        /// @return Returns remaining allowance for spender.
        function allowance(address _owner, address _spender)
            constant
            public
            returns (uint256)
        {
            return allowed[_owner][_spender];
        }
    
        /// @dev Returns number of tokens owned by the given address.
        /// @param _owner Address of token owner.
        /// @return Returns balance of owner.
        function balanceOf(address _owner) constant public returns (uint256) {
            return balances[_owner];
        }
    }
    
    
    /// @title Raiden Token
    contract RaidenToken is StandardToken {
    
        /*
         *  Terminology:
         *  1 token unit = Rei
         *  1 token = RDN = Rei * multiplier
         *  multiplier set from token's number of decimals (i.e. 10 ** decimals)
         */
    
        /*
         *  Token metadata
         */
        string constant public name = "Raiden Token";
        string constant public symbol = "RDN";
        uint8 constant public decimals = 18;
        uint constant multiplier = 10 ** uint(decimals);
    
        event Deployed(uint indexed _total_supply);
        event Burnt(
            address indexed _receiver,
            uint indexed _num,
            uint indexed _total_supply
        );
    
        /*
         *  Public functions
         */
        /// @dev Contract constructor function sets dutch auction contract address
        /// and assigns all tokens to dutch auction.
        /// @param auction_address Address of dutch auction contract.
        /// @param wallet_address Address of wallet.
        /// @param initial_supply Number of initially provided token units (Rei).
        function RaidenToken(
            address auction_address,
            address wallet_address,
            uint initial_supply)
            public
        {
            // Auction address should not be null.
            require(auction_address != 0x0);
            require(wallet_address != 0x0);
    
            // Initial supply is in Rei
            require(initial_supply > multiplier);
    
            // Total supply of Rei at deployment
            totalSupply = initial_supply;
    
            balances[auction_address] = initial_supply / 2;
            balances[wallet_address] = initial_supply / 2;
    
            Transfer(0x0, auction_address, balances[auction_address]);
            Transfer(0x0, wallet_address, balances[wallet_address]);
    
            Deployed(totalSupply);
    
            assert(totalSupply == balances[auction_address] + balances[wallet_address]);
        }
    
        /// @notice Allows `msg.sender` to simply destroy `num` token units (Rei). This means the total
        /// token supply will decrease.
        /// @dev Allows to destroy token units (Rei).
        /// @param num Number of token units (Rei) to burn.
        function burn(uint num) public {
            require(num > 0);
            require(balances[msg.sender] >= num);
            require(totalSupply >= num);
    
            uint pre_balance = balances[msg.sender];
    
            balances[msg.sender] -= num;
            totalSupply -= num;
            Burnt(msg.sender, num, totalSupply);
            Transfer(msg.sender, 0x0, num);
    
            assert(balances[msg.sender] == pre_balance - num);
        }
    
    }
    
    
    /// @title Dutch auction contract - distribution of a fixed number of tokens using an auction.
    /// The contract code is inspired by the Gnosis auction contract. Main difference is that the
    /// auction ends if a fixed number of tokens was sold.
    contract DutchAuction {
        /*
         * Auction for the RDN Token.
         *
         * Terminology:
         * 1 token unit = Rei
         * 1 token = RDN = Rei * token_multiplier
         * token_multiplier set from token's number of decimals (i.e. 10 ** decimals)
         */
    
        // Wait 7 days after the end of the auction, before anyone can claim tokens
        uint constant public token_claim_waiting_period = 7 days;
    
        // Bid value over which the address has to be whitelisted
        // At deployment moment, less than 1k$
        uint constant public bid_threshold = 2.5 ether;
    
        /*
         * Storage
         */
    
        RaidenToken public token;
        address public owner_address;
        address public wallet_address;
        address public whitelister_address;
    
        // Price decay function parameters to be changed depending on the desired outcome
    
        // Starting price in WEI; e.g. 2 * 10 ** 18
        uint public price_start;
    
        // Divisor constant; e.g. 524880000
        uint public price_constant;
    
        // Divisor exponent; e.g. 3
        uint32 public price_exponent;
    
        // For calculating elapsed time for price
        uint public start_time;
        uint public end_time;
        uint public start_block;
    
        // Keep track of all ETH received in the bids
        uint public received_wei;
    
        // Keep track of cumulative ETH funds for which the tokens have been claimed
        uint public funds_claimed;
    
        uint public token_multiplier;
    
        // Total number of Rei (RDN * token_multiplier) that will be auctioned
        uint public num_tokens_auctioned;
    
        // Wei per RDN (Rei * token_multiplier)
        uint public final_price;
    
        // Bidder address => bid value
        mapping (address => uint) public bids;
    
        // Whitelist for addresses that want to bid more than bid_threshold
        mapping (address => bool) public whitelist;
    
        Stages public stage;
    
        /*
         * Enums
         */
        enum Stages {
            AuctionDeployed,
            AuctionSetUp,
            AuctionStarted,
            AuctionEnded,
            TokensDistributed
        }
    
        /*
         * Modifiers
         */
        modifier atStage(Stages _stage) {
            require(stage == _stage);
            _;
        }
    
        modifier isOwner() {
            require(msg.sender == owner_address);
            _;
        }
    
        modifier isWhitelister() {
            require(msg.sender == whitelister_address);
            _;
        }
    
        /*
         * Events
         */
    
        event Deployed(
            uint indexed _price_start,
            uint indexed _price_constant,
            uint32 indexed _price_exponent
        );
        event Setup();
        event AuctionStarted(uint indexed _start_time, uint indexed _block_number);
        event BidSubmission(
            address indexed _sender,
            uint _amount,
            uint _missing_funds
        );
        event ClaimedTokens(address indexed _recipient, uint _sent_amount);
        event AuctionEnded(uint _final_price);
        event TokensDistributed();
    
        /*
         * Public functions
         */
    
        /// @dev Contract constructor function sets the starting price, divisor constant and
        /// divisor exponent for calculating the Dutch Auction price.
        /// @param _wallet_address Wallet address to which all contributed ETH will be forwarded.
        /// @param _price_start High price in WEI at which the auction starts.
        /// @param _price_constant Auction price divisor constant.
        /// @param _price_exponent Auction price divisor exponent.
        function DutchAuction(
            address _wallet_address,
            address _whitelister_address,
            uint _price_start,
            uint _price_constant,
            uint32 _price_exponent)
            public
        {
            require(_wallet_address != 0x0);
            require(_whitelister_address != 0x0);
            wallet_address = _wallet_address;
            whitelister_address = _whitelister_address;
    
            owner_address = msg.sender;
            stage = Stages.AuctionDeployed;
            changeSettings(_price_start, _price_constant, _price_exponent);
            Deployed(_price_start, _price_constant, _price_exponent);
        }
    
        /// @dev Fallback function for the contract, which calls bid() if the auction has started.
        function () public payable atStage(Stages.AuctionStarted) {
            bid();
        }
    
        /// @notice Set `_token_address` as the token address to be used in the auction.
        /// @dev Setup function sets external contracts addresses.
        /// @param _token_address Token address.
        function setup(address _token_address) public isOwner atStage(Stages.AuctionDeployed) {
            require(_token_address != 0x0);
            token = RaidenToken(_token_address);
    
            // Get number of Rei (RDN * token_multiplier) to be auctioned from token auction balance
            num_tokens_auctioned = token.balanceOf(address(this));
    
            // Set the number of the token multiplier for its decimals
            token_multiplier = 10 ** uint(token.decimals());
    
            stage = Stages.AuctionSetUp;
            Setup();
        }
    
        /// @notice Set `_price_start`, `_price_constant` and `_price_exponent` as
        /// the new starting price, price divisor constant and price divisor exponent.
        /// @dev Changes auction price function parameters before auction is started.
        /// @param _price_start Updated start price.
        /// @param _price_constant Updated price divisor constant.
        /// @param _price_exponent Updated price divisor exponent.
        function changeSettings(
            uint _price_start,
            uint _price_constant,
            uint32 _price_exponent)
            internal
        {
            require(stage == Stages.AuctionDeployed || stage == Stages.AuctionSetUp);
            require(_price_start > 0);
            require(_price_constant > 0);
    
            price_start = _price_start;
            price_constant = _price_constant;
            price_exponent = _price_exponent;
        }
    
        /// @notice Adds account addresses to whitelist.
        /// @dev Adds account addresses to whitelist.
        /// @param _bidder_addresses Array of addresses.
        function addToWhitelist(address[] _bidder_addresses) public isWhitelister {
            for (uint32 i = 0; i < _bidder_addresses.length; i++) {
                whitelist[_bidder_addresses[i]] = true;
            }
        }
    
        /// @notice Removes account addresses from whitelist.
        /// @dev Removes account addresses from whitelist.
        /// @param _bidder_addresses Array of addresses.
        function removeFromWhitelist(address[] _bidder_addresses) public isWhitelister {
            for (uint32 i = 0; i < _bidder_addresses.length; i++) {
                whitelist[_bidder_addresses[i]] = false;
            }
        }
    
        /// @notice Start the auction.
        /// @dev Starts auction and sets start_time.
        function startAuction() public isOwner atStage(Stages.AuctionSetUp) {
            stage = Stages.AuctionStarted;
            start_time = now;
            start_block = block.number;
            AuctionStarted(start_time, start_block);
        }
    
        /// @notice Finalize the auction - sets the final RDN token price and changes the auction
        /// stage after no bids are allowed anymore.
        /// @dev Finalize auction and set the final RDN token price.
        function finalizeAuction() public atStage(Stages.AuctionStarted)
        {
            // Missing funds should be 0 at this point
            uint missing_funds = missingFundsToEndAuction();
            require(missing_funds == 0);
    
            // Calculate the final price = WEI / RDN = WEI / (Rei / token_multiplier)
            // Reminder: num_tokens_auctioned is the number of Rei (RDN * token_multiplier) that are auctioned
            final_price = token_multiplier * received_wei / num_tokens_auctioned;
    
            end_time = now;
            stage = Stages.AuctionEnded;
            AuctionEnded(final_price);
    
            assert(final_price > 0);
        }
    
        /// --------------------------------- Auction Functions ------------------
    
    
        /// @notice Send `msg.value` WEI to the auction from the `msg.sender` account.
        /// @dev Allows to send a bid to the auction.
        function bid()
            public
            payable
            atStage(Stages.AuctionStarted)
        {
            require(msg.value > 0);
            require(bids[msg.sender] + msg.value <= bid_threshold || whitelist[msg.sender]);
            assert(bids[msg.sender] + msg.value >= msg.value);
    
            // Missing funds without the current bid value
            uint missing_funds = missingFundsToEndAuction();
    
            // We require bid values to be less than the funds missing to end the auction
            // at the current price.
            require(msg.value <= missing_funds);
    
            bids[msg.sender] += msg.value;
            received_wei += msg.value;
    
            // Send bid amount to wallet
            wallet_address.transfer(msg.value);
    
            BidSubmission(msg.sender, msg.value, missing_funds);
    
            assert(received_wei >= msg.value);
        }
    
        /// @notice Claim auction tokens for `msg.sender` after the auction has ended.
        /// @dev Claims tokens for `msg.sender` after auction. To be used if tokens can
        /// be claimed by beneficiaries, individually.
        function claimTokens() public atStage(Stages.AuctionEnded) returns (bool) {
            return proxyClaimTokens(msg.sender);
        }
    
        /// @notice Claim auction tokens for `receiver_address` after the auction has ended.
        /// @dev Claims tokens for `receiver_address` after auction has ended.
        /// @param receiver_address Tokens will be assigned to this address if eligible.
        function proxyClaimTokens(address receiver_address)
            public
            atStage(Stages.AuctionEnded)
            returns (bool)
        {
            // Waiting period after the end of the auction, before anyone can claim tokens
            // Ensures enough time to check if auction was finalized correctly
            // before users start transacting tokens
            require(now > end_time + token_claim_waiting_period);
            require(receiver_address != 0x0);
    
            if (bids[receiver_address] == 0) {
                return false;
            }
    
            // Number of Rei = bid_wei / Rei = bid_wei / (wei_per_RDN * token_multiplier)
            uint num = (token_multiplier * bids[receiver_address]) / final_price;
    
            // Due to final_price floor rounding, the number of assigned tokens may be higher
            // than expected. Therefore, the number of remaining unassigned auction tokens
            // may be smaller than the number of tokens needed for the last claimTokens call
            uint auction_tokens_balance = token.balanceOf(address(this));
            if (num > auction_tokens_balance) {
                num = auction_tokens_balance;
            }
    
            // Update the total amount of funds for which tokens have been claimed
            funds_claimed += bids[receiver_address];
    
            // Set receiver bid to 0 before assigning tokens
            bids[receiver_address] = 0;
    
            require(token.transfer(receiver_address, num));
    
            ClaimedTokens(receiver_address, num);
    
            // After the last tokens are claimed, we change the auction stage
            // Due to the above logic, rounding errors will not be an issue
            if (funds_claimed == received_wei) {
                stage = Stages.TokensDistributed;
                TokensDistributed();
            }
    
            assert(token.balanceOf(receiver_address) >= num);
            assert(bids[receiver_address] == 0);
            return true;
        }
    
        /// @notice Get the RDN price in WEI during the auction, at the time of
        /// calling this function. Returns `0` if auction has ended.
        /// Returns `price_start` before auction has started.
        /// @dev Calculates the current RDN token price in WEI.
        /// @return Returns WEI per RDN (token_multiplier * Rei).
        function price() public constant returns (uint) {
            if (stage == Stages.AuctionEnded ||
                stage == Stages.TokensDistributed) {
                return 0;
            }
            return calcTokenPrice();
        }
    
        /// @notice Get the missing funds needed to end the auction,
        /// calculated at the current RDN price in WEI.
        /// @dev The missing funds amount necessary to end the auction at the current RDN price in WEI.
        /// @return Returns the missing funds amount in WEI.
        function missingFundsToEndAuction() constant public returns (uint) {
    
            // num_tokens_auctioned = total number of Rei (RDN * token_multiplier) that is auctioned
            uint required_wei_at_price = num_tokens_auctioned * price() / token_multiplier;
            if (required_wei_at_price <= received_wei) {
                return 0;
            }
    
            // assert(required_wei_at_price - received_wei > 0);
            return required_wei_at_price - received_wei;
        }
    
        /*
         *  Private functions
         */
    
        /// @dev Calculates the token price (WEI / RDN) at the current timestamp
        /// during the auction; elapsed time = 0 before auction starts.
        /// Based on the provided parameters, the price does not change in the first
        /// `price_constant^(1/price_exponent)` seconds due to rounding.
        /// Rounding in `decay_rate` also produces values that increase instead of decrease
        /// in the beginning; these spikes decrease over time and are noticeable
        /// only in first hours. This should be calculated before usage.
        /// @return Returns the token price - Wei per RDN.
        function calcTokenPrice() constant private returns (uint) {
            uint elapsed;
            if (stage == Stages.AuctionStarted) {
                elapsed = now - start_time;
            }
    
            uint decay_rate = elapsed ** price_exponent / price_constant;
            return price_start * (1 + elapsed) / (1 + elapsed + decay_rate);
        }
    }

    File 2 of 2: MultiSigWalletWithDailyLimit
    pragma solidity 0.4.4;
    
    
    /// @title Multisignature wallet - Allows multiple parties to agree on transactions before execution.
    /// @author Stefan George - <stefan.george@consensys.net>
    contract MultiSigWallet {
    
        uint constant public MAX_OWNER_COUNT = 50;
    
        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);
    
        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() {
            if (msg.sender != address(this))
                throw;
            _;
        }
    
        modifier ownerDoesNotExist(address owner) {
            if (isOwner[owner])
                throw;
            _;
        }
    
        modifier ownerExists(address owner) {
            if (!isOwner[owner])
                throw;
            _;
        }
    
        modifier transactionExists(uint transactionId) {
            if (transactions[transactionId].destination == 0)
                throw;
            _;
        }
    
        modifier confirmed(uint transactionId, address owner) {
            if (!confirmations[transactionId][owner])
                throw;
            _;
        }
    
        modifier notConfirmed(uint transactionId, address owner) {
            if (confirmations[transactionId][owner])
                throw;
            _;
        }
    
        modifier notExecuted(uint transactionId) {
            if (transactions[transactionId].executed)
                throw;
            _;
        }
    
        modifier notNull(address _address) {
            if (_address == 0)
                throw;
            _;
        }
    
        modifier validRequirement(uint ownerCount, uint _required) {
            if (   ownerCount > MAX_OWNER_COUNT
                || _required > ownerCount
                || _required == 0
                || ownerCount == 0)
                throw;
            _;
        }
    
        /// @dev Fallback function allows to deposit ether.
        function()
            payable
        {
            if (msg.value > 0)
                Deposit(msg.sender, msg.value);
        }
    
        /*
         * Public functions
         */
        /// @dev Contract constructor sets initial owners and required number of confirmations.
        /// @param _owners List of initial owners.
        /// @param _required Number of required confirmations.
        function MultiSigWallet(address[] _owners, uint _required)
            public
            validRequirement(_owners.length, _required)
        {
            for (uint i=0; i<_owners.length; i++) {
                if (isOwner[_owners[i]] || _owners[i] == 0)
                    throw;
                isOwner[_owners[i]] = true;
            }
            owners = _owners;
            required = _required;
        }
    
        /// @dev Allows to add a new owner. Transaction has to be sent by wallet.
        /// @param owner Address of new owner.
        function addOwner(address owner)
            public
            onlyWallet
            ownerDoesNotExist(owner)
            notNull(owner)
            validRequirement(owners.length + 1, required)
        {
            isOwner[owner] = true;
            owners.push(owner);
            OwnerAddition(owner);
        }
    
        /// @dev Allows to remove an owner. Transaction has to be sent by wallet.
        /// @param owner Address of 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.length -= 1;
            if (required > owners.length)
                changeRequirement(owners.length);
            OwnerRemoval(owner);
        }
    
        /// @dev Allows to replace an owner with a new owner. Transaction has to be sent by wallet.
        /// @param owner Address of owner to be replaced.
        /// @param owner Address of new 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;
            OwnerRemoval(owner);
            OwnerAddition(newOwner);
        }
    
        /// @dev Allows to change the number of required confirmations. Transaction has to be sent by wallet.
        /// @param _required Number of required confirmations.
        function changeRequirement(uint _required)
            public
            onlyWallet
            validRequirement(owners.length, _required)
        {
            required = _required;
            RequirementChange(_required);
        }
    
        /// @dev Allows an owner to submit and confirm a transaction.
        /// @param destination Transaction target address.
        /// @param value Transaction ether value.
        /// @param data Transaction data payload.
        /// @return Returns transaction ID.
        function submitTransaction(address destination, uint value, bytes data)
            public
            returns (uint transactionId)
        {
            transactionId = addTransaction(destination, value, data);
            confirmTransaction(transactionId);
        }
    
        /// @dev Allows an owner to confirm a transaction.
        /// @param transactionId Transaction ID.
        function confirmTransaction(uint transactionId)
            public
            ownerExists(msg.sender)
            transactionExists(transactionId)
            notConfirmed(transactionId, msg.sender)
        {
            confirmations[transactionId][msg.sender] = true;
            Confirmation(msg.sender, transactionId);
            executeTransaction(transactionId);
        }
    
        /// @dev Allows an owner to revoke a confirmation for a transaction.
        /// @param transactionId Transaction ID.
        function revokeConfirmation(uint transactionId)
            public
            ownerExists(msg.sender)
            confirmed(transactionId, msg.sender)
            notExecuted(transactionId)
        {
            confirmations[transactionId][msg.sender] = false;
            Revocation(msg.sender, transactionId);
        }
    
        /// @dev Allows anyone to execute a confirmed transaction.
        /// @param transactionId Transaction ID.
        function executeTransaction(uint transactionId)
            public
            notExecuted(transactionId)
        {
            if (isConfirmed(transactionId)) {
                Transaction tx = transactions[transactionId];
                tx.executed = true;
                if (tx.destination.call.value(tx.value)(tx.data))
                    Execution(transactionId);
                else {
                    ExecutionFailure(transactionId);
                    tx.executed = false;
                }
            }
        }
    
        /// @dev Returns the confirmation status of a transaction.
        /// @param transactionId Transaction ID.
        /// @return Confirmation status.
        function isConfirmed(uint transactionId)
            public
            constant
            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;
            }
        }
    
        /*
         * Internal functions
         */
        /// @dev Adds a new transaction to the transaction mapping, if transaction does not exist yet.
        /// @param destination Transaction target address.
        /// @param value Transaction ether value.
        /// @param data Transaction data payload.
        /// @return Returns transaction ID.
        function addTransaction(address destination, uint value, bytes data)
            internal
            notNull(destination)
            returns (uint transactionId)
        {
            transactionId = transactionCount;
            transactions[transactionId] = Transaction({
                destination: destination,
                value: value,
                data: data,
                executed: false
            });
            transactionCount += 1;
            Submission(transactionId);
        }
    
        /*
         * Web3 call functions
         */
        /// @dev Returns number of confirmations of a transaction.
        /// @param transactionId Transaction ID.
        /// @return Number of confirmations.
        function getConfirmationCount(uint transactionId)
            public
            constant
            returns (uint count)
        {
            for (uint i=0; i<owners.length; i++)
                if (confirmations[transactionId][owners[i]])
                    count += 1;
        }
    
        /// @dev Returns total number of transactions after filers are applied.
        /// @param pending Include pending transactions.
        /// @param executed Include executed transactions.
        /// @return Total number of transactions after filters are applied.
        function getTransactionCount(bool pending, bool executed)
            public
            constant
            returns (uint count)
        {
            for (uint i=0; i<transactionCount; i++)
                if (   pending && !transactions[i].executed
                    || executed && transactions[i].executed)
                    count += 1;
        }
    
        /// @dev Returns list of owners.
        /// @return List of owner addresses.
        function getOwners()
            public
            constant
            returns (address[])
        {
            return owners;
        }
    
        /// @dev Returns array with owner addresses, which confirmed transaction.
        /// @param transactionId Transaction ID.
        /// @return Returns array of owner addresses.
        function getConfirmations(uint transactionId)
            public
            constant
            returns (address[] _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];
        }
    
        /// @dev Returns list of transaction IDs in defined range.
        /// @param from Index start position of transaction array.
        /// @param to Index end position of transaction array.
        /// @param pending Include pending transactions.
        /// @param executed Include executed transactions.
        /// @return Returns array of transaction IDs.
        function getTransactionIds(uint from, uint to, bool pending, bool executed)
            public
            constant
            returns (uint[] _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];
        }
    }
    
    
    /// @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.
        function MultiSigWalletWithDailyLimit(address[] _owners, uint _required, uint _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(uint _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
            notExecuted(transactionId)
        {
            Transaction tx = transactions[transactionId];
            bool confirmed = isConfirmed(transactionId);
            if (confirmed || tx.data.length == 0 && isUnderLimit(tx.value)) {
                tx.executed = true;
                if (!confirmed)
                    spentToday += tx.value;
                if (tx.destination.call.value(tx.value)(tx.data))
                    Execution(transactionId);
                else {
                    ExecutionFailure(transactionId);
                    tx.executed = false;
                    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)
        {
            if (now > lastDay + 24 hours) {
                lastDay = now;
                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
            constant
            returns (uint)
        {
            if (now > lastDay + 24 hours)
                return dailyLimit;
            if (dailyLimit < spentToday)
                return 0;
            return dailyLimit - spentToday;
        }
    }