ETH Price: $2,413.54 (-0.28%)

Transaction Decoder

Block:
4036139 at Jul-17-2017 07:56:49 PM +UTC
Transaction Fee:
0.00298995 ETH $7.22
Gas Used:
59,799 Gas / 50 Gwei

Emitted Events:

6 MultiSigWalletWithDailyLimit.Deposit( sender=[Receiver] PillarToken, value=500000000000000000 )
7 PillarToken.Transfer( from=0x0000000000000000000000000000000000000000, to=[Sender] 0x192b42ab7d551e6674fd640d1a7dda01b7d57208, value=1000000000000000000000 )

Account State Difference:

  Address   Before After State Difference Code
0x05A9aFD7...9366B160B 93,625.512019699451134044 Eth93,626.012019699451134044 Eth0.5
0x192b42aB...1B7D57208
0.578796248527894018 Eth
Nonce: 59
0.075806298527894018 Eth
Nonce: 60
0.50298995
(ethfans.org)
1,588.898658974580340175 Eth1,588.901648924580340175 Eth0.00298995
0xe3818504...Fd3149C17

Execution Trace

ETH 0.5 PillarToken.CALL( )
  • ETH 0.5 MultiSigWalletWithDailyLimit.CALL( )
    File 1 of 2: PillarToken
    pragma solidity ^0.4.11;
    
    
    /**
     * Math operations with safety checks
     */
    library SafeMath {
      function mul(uint a, uint b) internal returns (uint) {
        uint c = a * b;
        assert(a == 0 || c / a == b);
        return c;
      }
    
      function div(uint a, uint b) internal returns (uint) {
        // assert(b > 0); // Solidity automatically throws when dividing by 0
        uint c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold
        return c;
      }
    
      function sub(uint a, uint b) internal returns (uint) {
        assert(b <= a);
        return a - b;
      }
    
      function add(uint a, uint b) internal returns (uint) {
        uint c = a + b;
        assert(c >= a);
        return c;
      }
    
      function max64(uint64 a, uint64 b) internal constant returns (uint64) {
        return a >= b ? a : b;
      }
    
      function min64(uint64 a, uint64 b) internal constant returns (uint64) {
        return a < b ? a : b;
      }
    
      function max256(uint256 a, uint256 b) internal constant returns (uint256) {
        return a >= b ? a : b;
      }
    
      function min256(uint256 a, uint256 b) internal constant returns (uint256) {
        return a < b ? a : b;
      }
    
      function assert(bool assertion) internal {
        if (!assertion) {
          throw;
        }
      }
    }
    
    /**
     * @title Ownable
     * @dev The Ownable contract has an owner address, and provides basic authorization control 
     * functions, this simplifies the implementation of "user permissions". 
     */
    contract Ownable {
      address public owner;
    
    
      /** 
       * @dev The Ownable constructor sets the original `owner` of the contract to the sender
       * account.
       */
      function Ownable() {
        owner = msg.sender;
      }
    
    
      /**
       * @dev Throws if called by any account other than the owner. 
       */
      modifier onlyOwner() {
        if (msg.sender != owner) {
          throw;
        }
        _;
      }
    
    
      /**
       * @dev Allows the current owner to transfer control of the contract to a newOwner.
       * @param newOwner The address to transfer ownership to. 
       */
      function transferOwnership(address newOwner) onlyOwner {
        if (newOwner != address(0)) {
          owner = newOwner;
        }
      }
    
    }
    
    contract TeamAllocation is Ownable {
      using SafeMath for uint;
      //uint public constant lockedTeamAllocationTokens = 16000000;
      uint public unlockedAt;
      PillarToken plr;
      mapping (address => uint) allocations;
      uint tokensCreated = 0;
      uint constant public lockedTeamAllocationTokens = 16000000e18;
      //address of the team storage vault
      address public teamStorageVault = 0x3f5D90D5Cc0652AAa40519114D007Bf119Afe1Cf;
    
      function TeamAllocation() {
        plr = PillarToken(msg.sender);
        // Locked time of approximately 9 months before team members are able to redeeem tokens.
        uint nineMonths = 9 * 30 days;
        unlockedAt = now.add(nineMonths);
        //2% tokens from the Marketing bucket which are locked for 9 months
        allocations[teamStorageVault] = lockedTeamAllocationTokens;
      }
    
      function getTotalAllocation() returns (uint){
          return lockedTeamAllocationTokens;
      }
    
      function unlock() external payable {
        if (now < unlockedAt) throw;
    
        if (tokensCreated == 0) {
          tokensCreated = plr.balanceOf(this);
        }
        //transfer the locked tokens to the teamStorageAddress
        plr.transfer(teamStorageVault, tokensCreated);
      }
    }
    
    contract UnsoldAllocation is Ownable {
      using SafeMath for uint;
      uint unlockedAt;
      uint allocatedTokens;
      PillarToken plr;
      mapping (address => uint) allocations;
    
      uint tokensCreated = 0;
    
      /*
        Split among team members
        Tokens reserved for Team: 1,000,000
        Tokens reserved for 20|30 projects: 1,000,000
        Tokens reserved for future sale: 1,000,000
      */
    
      function UnsoldAllocation(uint _lockTime, address _owner, uint _tokens) {
        if(_lockTime == 0) throw;
    
        if(_owner == address(0)) throw;
    
        plr = PillarToken(msg.sender);
        uint lockTime = _lockTime * 1 years;
        unlockedAt = now.add(lockTime);
        allocatedTokens = _tokens;
        allocations[_owner] = _tokens;
      }
    
      function getTotalAllocation()returns(uint){
          return allocatedTokens;
      }
    
      function unlock() external payable {
        if (now < unlockedAt) throw;
    
        if (tokensCreated == 0) {
          tokensCreated = plr.balanceOf(this);
        }
    
        var allocation = allocations[msg.sender];
        allocations[msg.sender] = 0;
        var toTransfer = (tokensCreated.mul(allocation)).div(allocatedTokens);
        plr.transfer(msg.sender, toTransfer);
      }
    }
    
    /**
     * @title Pausable
     * @dev Base contract which allows children to implement an emergency stop mechanism.
     */
    contract Pausable is Ownable {
      event Pause();
      event Unpause();
    
      bool public paused = false;
    
    
      /**
       * @dev modifier to allow actions only when the contract IS paused
       */
      modifier whenNotPaused() {
        if (paused) throw;
        _;
      }
    
      /**
       * @dev modifier to allow actions only when the contract IS NOT paused
       */
      modifier whenPaused {
        if (!paused) throw;
        _;
      }
    
      /**
       * @dev called by the owner to pause, triggers stopped state
       */
      function pause() onlyOwner whenNotPaused returns (bool) {
        paused = true;
        Pause();
        return true;
      }
    
      /**
       * @dev called by the owner to unpause, returns to normal state
       */
      function unpause() onlyOwner whenPaused returns (bool) {
        paused = false;
        Unpause();
        return true;
      }
    }
    
    
    /**
     * @title ERC20Basic
     * @dev Simpler version of ERC20 interface
     * @dev see https://github.com/ethereum/EIPs/issues/20
     */
    contract ERC20Basic {
      uint public totalSupply;
      function balanceOf(address who) constant returns (uint);
      function transfer(address to, uint value);
      event Transfer(address indexed from, address indexed to, uint value);
    }
    
    /**
     * @title Basic token
     * @dev Basic version of StandardToken, with no allowances. 
     */
    contract BasicToken is ERC20Basic {
      using SafeMath for uint;
    
      mapping(address => uint) balances;
    
      /**
       * @dev Fix for the ERC20 short address attack.
       */
      modifier onlyPayloadSize(uint size) {
         if(msg.data.length < size + 4) {
           throw;
         }
         _;
      }
    
      /**
      * @dev transfer token for a specified address
      * @param _to The address to transfer to.
      * @param _value The amount to be transferred.
      */
      function transfer(address _to, uint _value) onlyPayloadSize(2 * 32) {
        balances[msg.sender] = balances[msg.sender].sub(_value);
        balances[_to] = balances[_to].add(_value);
        Transfer(msg.sender, _to, _value);
      }
    
      /**
      * @dev Gets the balance of the specified address.
      * @param _owner The address to query the the balance of. 
      * @return An uint representing the amount owned by the passed address.
      */
      function balanceOf(address _owner) constant returns (uint balance) {
        return balances[_owner];
      }
    
    }
    
    /**
     * @title ERC20 interface
     * @dev see https://github.com/ethereum/EIPs/issues/20
     */
    contract ERC20 is ERC20Basic {
      function allowance(address owner, address spender) constant returns (uint);
      function transferFrom(address from, address to, uint value);
      function approve(address spender, uint value);
      event Approval(address indexed owner, address indexed spender, uint value);
    }
    
    /**
     * @title Standard ERC20 token
     *
     * @dev Implemantation of the basic standart token.
     * @dev https://github.com/ethereum/EIPs/issues/20
     * @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
     */
    contract StandardToken is BasicToken, ERC20 {
    
      mapping (address => mapping (address => uint)) allowed;
    
    
      /**
       * @dev Transfer tokens from one address to another
       * @param _from address The address which you want to send tokens from
       * @param _to address The address which you want to transfer to
       * @param _value uint the amout of tokens to be transfered
       */
      function transferFrom(address _from, address _to, uint _value) onlyPayloadSize(3 * 32) {
        var _allowance = allowed[_from][msg.sender];
    
        // Check is not needed because sub(_allowance, _value) will already throw if this condition is not met
        // if (_value > _allowance) throw;
    
        balances[_to] = balances[_to].add(_value);
        balances[_from] = balances[_from].sub(_value);
        allowed[_from][msg.sender] = _allowance.sub(_value);
        Transfer(_from, _to, _value);
      }
    
      /**
       * @dev Aprove the passed address to spend the specified amount of tokens on beahlf of msg.sender.
       * @param _spender The address which will spend the funds.
       * @param _value The amount of tokens to be spent.
       */
      function approve(address _spender, uint _value) {
    
        // 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
        if ((_value != 0) && (allowed[msg.sender][_spender] != 0)) throw;
    
        allowed[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);
      }
    
      /**
       * @dev Function to check the amount of tokens than an owner allowed to a spender.
       * @param _owner address The address which owns the funds.
       * @param _spender address The address which will spend the funds.
       * @return A uint specifing the amount of tokens still avaible for the spender.
       */
      function allowance(address _owner, address _spender) constant returns (uint remaining) {
        return allowed[_owner][_spender];
      }
    
    }
    
    /// @title PillarToken - Crowdfunding code for the Pillar Project
    /// @author Parthasarathy Ramanujam, Gustavo Guimaraes, Ronak Thacker
    contract PillarToken is StandardToken, Ownable {
    
        using SafeMath for uint;
        string public constant name = "PILLAR";
        string public constant symbol = "PLR";
        uint public constant decimals = 18;
    
        TeamAllocation public teamAllocation;
        UnsoldAllocation public unsoldTokens;
        UnsoldAllocation public twentyThirtyAllocation;
        UnsoldAllocation public futureSaleAllocation;
    
        uint constant public minTokensForSale  = 32000000e18;
    
        uint constant public maxPresaleTokens             =  48000000e18;
        uint constant public totalAvailableForSale        = 528000000e18;
        uint constant public futureTokens                 = 120000000e18;
        uint constant public twentyThirtyTokens           =  80000000e18;
        uint constant public lockedTeamAllocationTokens   =  16000000e18;
        uint constant public unlockedTeamAllocationTokens =   8000000e18;
    
        address public unlockedTeamStorageVault = 0x4162Ad6EEc341e438eAbe85f52a941B078210819;
        address public twentyThirtyVault = 0xe72bA5c6F63Ddd395DF9582800E2821cE5a05D75;
        address public futureSaleVault = 0xf0231160Bd1a2a2D25aed2F11B8360EbF56F6153;
        address unsoldVault;
    
        //Storage years
        uint constant coldStorageYears = 10;
        uint constant futureStorageYears = 3;
    
        uint totalPresale = 0;
    
        // Funding amount in ether
        uint public constant tokenPrice  = 0.0005 ether;
    
        // Multisigwallet where the proceeds will be stored.
        address public pillarTokenFactory;
    
        uint fundingStartBlock;
        uint fundingStopBlock;
    
        // flags whether ICO is afoot.
        bool fundingMode;
    
        //total used tokens
        uint totalUsedTokens;
    
        event Refund(address indexed _from,uint256 _value);
        event Migrate(address indexed _from, address indexed _to, uint256 _value);
        event MoneyAddedForRefund(address _from, uint256 _value,uint256 _total);
    
        modifier isNotFundable() {
            if (fundingMode) throw;
            _;
        }
    
        modifier isFundable() {
            if (!fundingMode) throw;
            _;
        }
    
        //@notice  Constructor of PillarToken
        //@param `_pillarTokenFactory` - multisigwallet address to store proceeds.
        //@param `_icedWallet` - Multisigwallet address to which unsold tokens are assigned
        function PillarToken(address _pillarTokenFactory, address _icedWallet) {
          if(_pillarTokenFactory == address(0)) throw;
          if(_icedWallet == address(0)) throw;
    
          pillarTokenFactory = _pillarTokenFactory;
          totalUsedTokens = 0;
          totalSupply = 800000000e18;
          unsoldVault = _icedWallet;
    
          //allot 8 million of the 24 million marketing tokens to an address
          balances[unlockedTeamStorageVault] = unlockedTeamAllocationTokens;
    
          //allocate tokens for 2030 wallet locked in for 3 years
          futureSaleAllocation = new UnsoldAllocation(futureStorageYears,futureSaleVault,futureTokens);
          balances[address(futureSaleAllocation)] = futureTokens;
    
          //allocate tokens for future wallet locked in for 3 years
          twentyThirtyAllocation = new UnsoldAllocation(futureStorageYears,twentyThirtyVault,twentyThirtyTokens);
          balances[address(twentyThirtyAllocation)] = twentyThirtyTokens;
    
          fundingMode = false;
        }
    
        //@notice Fallback function that accepts the ether and allocates tokens to
        //the msg.sender corresponding to msg.value
        function() payable isFundable external {
          purchase();
        }
    
        //@notice function that accepts the ether and allocates tokens to
        //the msg.sender corresponding to msg.value
        function purchase() payable isFundable {
          if(block.number < fundingStartBlock) throw;
          if(block.number > fundingStopBlock) throw;
          if(totalUsedTokens >= totalAvailableForSale) throw;
    
          if (msg.value < tokenPrice) throw;
    
          uint numTokens = msg.value.div(tokenPrice);
          if(numTokens < 1) throw;
          //transfer money to PillarTokenFactory MultisigWallet
          pillarTokenFactory.transfer(msg.value);
    
          uint tokens = numTokens.mul(1e18);
          totalUsedTokens = totalUsedTokens.add(tokens);
          if (totalUsedTokens > totalAvailableForSale) throw;
    
          balances[msg.sender] = balances[msg.sender].add(tokens);
    
          //fire the event notifying the transfer of tokens
          Transfer(0, msg.sender, tokens);
        }
    
        //@notice Function reports the number of tokens available for sale
        function numberOfTokensLeft() constant returns (uint256) {
          uint tokensAvailableForSale = totalAvailableForSale.sub(totalUsedTokens);
          return tokensAvailableForSale;
        }
    
        //@notice Finalize the ICO, send team allocation tokens
        //@notice send any remaining balance to the MultisigWallet
        //@notice unsold tokens will be sent to icedwallet
        function finalize() isFundable onlyOwner external {
          if (block.number <= fundingStopBlock) throw;
    
          if (totalUsedTokens < minTokensForSale) throw;
    
          if(unsoldVault == address(0)) throw;
    
          // switch funding mode off
          fundingMode = false;
    
          //Allot team tokens to a smart contract which will frozen for 9 months
          teamAllocation = new TeamAllocation();
          balances[address(teamAllocation)] = lockedTeamAllocationTokens;
    
          //allocate unsold tokens to iced storage
          uint totalUnSold = numberOfTokensLeft();
          if(totalUnSold > 0) {
            unsoldTokens = new UnsoldAllocation(coldStorageYears,unsoldVault,totalUnSold);
            balances[address(unsoldTokens)] = totalUnSold;
          }
    
          //transfer any balance available to Pillar Multisig Wallet
          pillarTokenFactory.transfer(this.balance);
        }
    
        //@notice Function that can be called by purchasers to refund
        //@notice Used only in case the ICO isn't successful.
        function refund() isFundable external {
          if(block.number <= fundingStopBlock) throw;
          if(totalUsedTokens >= minTokensForSale) throw;
    
          uint plrValue = balances[msg.sender];
          if(plrValue == 0) throw;
    
          balances[msg.sender] = 0;
    
          uint ethValue = plrValue.mul(tokenPrice).div(1e18);
          msg.sender.transfer(ethValue);
          Refund(msg.sender, ethValue);
        }
    
        //@notice Function used for funding in case of refund.
        //@notice Can be called only by the Owner
        function allocateForRefund() external payable onlyOwner returns (uint){
          //does nothing just accepts and stores the ether
          MoneyAddedForRefund(msg.sender,msg.value,this.balance);
          return this.balance;
        }
    
        //@notice Function to allocate tokens to an user.
        //@param `_to` the address of an user
        //@param `_tokens` number of tokens to be allocated.
        //@notice Can be called only when funding is not active and only by the owner
        function allocateTokens(address _to,uint _tokens) isNotFundable onlyOwner external {
          uint numOfTokens = _tokens.mul(1e18);
          totalPresale = totalPresale.add(numOfTokens);
    
          if(totalPresale > maxPresaleTokens) throw;
    
          balances[_to] = balances[_to].add(numOfTokens);
        }
    
        //@notice Function to unPause the contract.
        //@notice Can be called only when funding is active and only by the owner
        function unPauseTokenSale() onlyOwner isNotFundable external returns (bool){
          fundingMode = true;
          return fundingMode;
        }
    
        //@notice Function to pause the contract.
        //@notice Can be called only when funding is active and only by the owner
        function pauseTokenSale() onlyOwner isFundable external returns (bool){
          fundingMode = false;
          return !fundingMode;
        }
    
        //@notice Function to start the contract.
        //@param `_fundingStartBlock` - block from when ICO commences
        //@param `_fundingStopBlock` - block from when ICO ends.
        //@notice Can be called only when funding is not active and only by the owner
        function startTokenSale(uint _fundingStartBlock, uint _fundingStopBlock) onlyOwner isNotFundable external returns (bool){
          if(_fundingStopBlock <= _fundingStartBlock) throw;
    
          fundingStartBlock = _fundingStartBlock;
          fundingStopBlock = _fundingStopBlock;
          fundingMode = true;
          return fundingMode;
        }
    
        //@notice Function to get the current funding status.
        function fundingStatus() external constant returns (bool){
          return fundingMode;
        }
    }

    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 - <[email protected]>
    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 - <[email protected]>
    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;
            return dailyLimit - spentToday;
        }
    }