ETH Price: $2,315.18 (+1.62%)

Transaction Decoder

Block:
5013427 at Feb-01-2018 08:45:50 PM +UTC
Transaction Fee:
0.002299766 ETH $5.32
Gas Used:
74,186 Gas / 31 Gwei

Emitted Events:

101 BeeToken.Transfer( from=0x77856D50941e1b5b29e291B083740e05E800883A, to=[Sender] 0xd8bef84daf322b79e5c325a46ce1c4d7edf4759b, value=445000000000000000000 )
102 MultiSigWalletWithDailyLimit.Deposit( sender=[Receiver] BeeTokenOffering, value=100000000000000000 )
103 BeeTokenOffering.TokenPurchase( purchaser=[Sender] 0xd8bef84daf322b79e5c325a46ce1c4d7edf4759b, value=100000000000000000, amount=445000000000000000000 )

Account State Difference:

  Address   Before After State Difference Code
0x4D8fc145...80d996FbF
0x62CAf75a...0C7434B7F
(Bee Token: Token Sale)
0x7C4b4BB0...d456726c6
(Bee Token: MultiSig)
3,671.443689104883906904 Eth3,671.543689104883906904 Eth0.1
0xD8BEf84d...7edF4759b
0.982486705 Eth
Nonce: 5
0.880186939 Eth
Nonce: 6
0.102299766
(Ethermine)
851.787741999953466948 Eth851.790041765953466948 Eth0.002299766

Execution Trace

ETH 0.1 BeeTokenOffering.CALL( )
  • BeeToken.CALL( )
  • BeeToken.transferFrom( from=0x77856D50941e1b5b29e291B083740e05E800883A, to=0xD8BEf84daf322B79e5C325A46cE1C4D7edF4759b, value=445000000000000000000 ) => ( True )
  • ETH 0.1 MultiSigWalletWithDailyLimit.CALL( )
    File 1 of 3: BeeTokenOffering
    pragma solidity ^0.4.18;
    
    /**
     * @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;
    
    
      event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    
    
      /**
       * @dev The Ownable constructor sets the original `owner` of the contract to the sender
       * account.
       */
      function Ownable() public {
        owner = msg.sender;
      }
    
    
      /**
       * @dev Throws if called by any account other than the owner.
       */
      modifier onlyOwner() {
        require(msg.sender == owner);
        _;
      }
    
    
      /**
       * @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) public onlyOwner {
        require(newOwner != address(0));
        OwnershipTransferred(owner, newOwner);
        owner = newOwner;
      }
    
    }
    
    /**
     * @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 make a function callable only when the contract is not paused.
       */
      modifier whenNotPaused() {
        require(!paused);
        _;
      }
    
      /**
       * @dev Modifier to make a function callable only when the contract is paused.
       */
      modifier whenPaused() {
        require(paused);
        _;
      }
    
      /**
       * @dev called by the owner to pause, triggers stopped state
       */
      function pause() onlyOwner whenNotPaused public {
        paused = true;
        Pause();
      }
    
      /**
       * @dev called by the owner to unpause, returns to normal state
       */
      function unpause() onlyOwner whenPaused public {
        paused = false;
        Unpause();
      }
    }
    
    /**
     * @title SafeMath
     * @dev Math operations with safety checks that throw on error
     */
    library SafeMath {
      function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) {
          return 0;
        }
        uint256 c = a * b;
        assert(c / a == b);
        return c;
      }
    
      function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // assert(b > 0); // Solidity automatically throws when dividing by 0
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold
        return c;
      }
    
      function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        assert(b <= a);
        return a - b;
      }
    
      function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        assert(c >= a);
        return c;
      }
    }
    
    /**
     * @title ERC20Basic
     * @dev Simpler version of ERC20 interface
     * @dev see https://github.com/ethereum/EIPs/issues/179
     */
    contract ERC20Basic {
      uint256 public totalSupply;
      function balanceOf(address who) public view returns (uint256);
      function transfer(address to, uint256 value) public returns (bool);
      event Transfer(address indexed from, address indexed to, uint256 value);
    }
    
    /**
     * @title ERC20 interface
     * @dev see https://github.com/ethereum/EIPs/issues/20
     */
    contract ERC20 is ERC20Basic {
      function allowance(address owner, address spender) public view returns (uint256);
      function transferFrom(address from, address to, uint256 value) public returns (bool);
      function approve(address spender, uint256 value) public returns (bool);
      event Approval(address indexed owner, address indexed spender, uint256 value);
    }
    
    /**
     * @title Basic token
     * @dev Basic version of StandardToken, with no allowances.
     */
    contract BasicToken is ERC20Basic {
      using SafeMath for uint256;
    
      mapping(address => uint256) balances;
    
      /**
      * @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, uint256 _value) public returns (bool) {
        require(_to != address(0));
        require(_value <= balances[msg.sender]);
    
        // SafeMath.sub will throw if there is not enough balance.
        balances[msg.sender] = balances[msg.sender].sub(_value);
        balances[_to] = balances[_to].add(_value);
        Transfer(msg.sender, _to, _value);
        return true;
      }
    
      /**
      * @dev Gets the balance of the specified address.
      * @param _owner The address to query the the balance of.
      * @return An uint256 representing the amount owned by the passed address.
      */
      function balanceOf(address _owner) public view returns (uint256 balance) {
        return balances[_owner];
      }
    
    }
    
    /**
     * @title Burnable Token
     * @dev Token that can be irreversibly burned (destroyed).
     */
    contract BurnableToken is BasicToken {
    
        event Burn(address indexed burner, uint256 value);
    
        /**
         * @dev Burns a specific amount of tokens.
         * @param _value The amount of token to be burned.
         */
        function burn(uint256 _value) public {
            require(_value <= balances[msg.sender]);
            // no need to require value <= totalSupply, since that would imply the
            // sender's balance is greater than the totalSupply, which *should* be an assertion failure
    
            address burner = msg.sender;
            balances[burner] = balances[burner].sub(_value);
            totalSupply = totalSupply.sub(_value);
            Burn(burner, _value);
        }
    }
    
    
    /**
     * @title Standard ERC20 token
     *
     * @dev Implementation of the basic standard 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 ERC20, BasicToken {
    
      mapping (address => mapping (address => uint256)) internal 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 uint256 the amount of tokens to be transferred
       */
      function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
        require(_to != address(0));
        require(_value <= balances[_from]);
        require(_value <= allowed[_from][msg.sender]);
    
        balances[_from] = balances[_from].sub(_value);
        balances[_to] = balances[_to].add(_value);
        allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
        Transfer(_from, _to, _value);
        return true;
      }
    
      /**
       * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
       *
       * Beware that changing an allowance with this method brings the risk that someone may use both the old
       * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
       * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
       * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
       * @param _spender The address which will spend the funds.
       * @param _value The amount of tokens to be spent.
       */
      function approve(address _spender, uint256 _value) public returns (bool) {
        allowed[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);
        return true;
      }
    
      /**
       * @dev Function to check the amount of tokens that 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 uint256 specifying the amount of tokens still available for the spender.
       */
      function allowance(address _owner, address _spender) public view returns (uint256) {
        return allowed[_owner][_spender];
      }
    
      /**
       * @dev Increase the amount of tokens that an owner allowed to a spender.
       *
       * approve should be called when allowed[_spender] == 0. To increment
       * allowed value is better to use this function to avoid 2 calls (and wait until
       * the first transaction is mined)
       * From MonolithDAO Token.sol
       * @param _spender The address which will spend the funds.
       * @param _addedValue The amount of tokens to increase the allowance by.
       */
      function increaseApproval(address _spender, uint _addedValue) public returns (bool) {
        allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue);
        Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
        return true;
      }
    
      /**
       * @dev Decrease the amount of tokens that an owner allowed to a spender.
       *
       * approve should be called when allowed[_spender] == 0. To decrement
       * allowed value is better to use this function to avoid 2 calls (and wait until
       * the first transaction is mined)
       * From MonolithDAO Token.sol
       * @param _spender The address which will spend the funds.
       * @param _subtractedValue The amount of tokens to decrease the allowance by.
       */
      function decreaseApproval(address _spender, uint _subtractedValue) public returns (bool) {
        uint oldValue = allowed[msg.sender][_spender];
        if (_subtractedValue > oldValue) {
          allowed[msg.sender][_spender] = 0;
        } else {
          allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);
        }
        Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
        return true;
      }
    
    }
    
    
    /*
     * BeeToken is a standard ERC20 token with some additional functionalities:
     * - Transfers are only enabled after contract owner enables it (after the ICO)
     * - Contract sets 30% of the total supply as allowance for ICO contract
     *
     * Note: Token Offering == Initial Coin Offering(ICO)
     */
    
    contract BeeToken is StandardToken, BurnableToken, Ownable {
        string public constant symbol = "BEE";
        string public constant name = "Bee Token";
        uint8 public constant decimals = 18;
        uint256 public constant INITIAL_SUPPLY = 500000000 * (10 ** uint256(decimals));
        uint256 public constant TOKEN_OFFERING_ALLOWANCE = 150000000 * (10 ** uint256(decimals));
        uint256 public constant ADMIN_ALLOWANCE = INITIAL_SUPPLY - TOKEN_OFFERING_ALLOWANCE;
        
        // Address of token admin
        address public adminAddr;
        // Address of token offering
        address public tokenOfferingAddr;
        // Enable transfers after conclusion of token offering
        bool public transferEnabled = false;
        
        /**
         * Check if transfer is allowed
         *
         * Permissions:
         *                                                       Owner    Admin    OffeirngContract    Others
         * transfer (before transferEnabled is true)               x        x            x               x
         * transferFrom (before transferEnabled is true)           x        v            v               x
         * transfer/transferFrom after transferEnabled is true     v        x            x               v
         */
        modifier onlyWhenTransferAllowed() {
            require(transferEnabled || msg.sender == adminAddr || msg.sender == tokenOfferingAddr);
            _;
        }
    
        /**
         * Check if token offering address is set or not
         */
        modifier onlyTokenOfferingAddrNotSet() {
            require(tokenOfferingAddr == address(0x0));
            _;
        }
    
        /**
         * Check if address is a valid destination to transfer tokens to
         * - must not be zero address
         * - must not be the token address
         * - must not be the owner's address
         * - must not be the admin's address
         * - must not be the token offering contract address
         */
        modifier validDestination(address to) {
            require(to != address(0x0));
            require(to != address(this));
            require(to != owner);
            require(to != address(adminAddr));
            require(to != address(tokenOfferingAddr));
            _;
        }
        
        /**
         * Token contract constructor
         *
         * @param admin Address of admin account
         */
        function BeeToken(address admin) public {
            totalSupply = INITIAL_SUPPLY;
            
            // Mint tokens
            balances[msg.sender] = totalSupply;
            Transfer(address(0x0), msg.sender, totalSupply);
    
            // Approve allowance for admin account
            adminAddr = admin;
            approve(adminAddr, ADMIN_ALLOWANCE);
        }
    
        /**
         * Set token offering to approve allowance for offering contract to distribute tokens
         *
         * @param offeringAddr Address of token offerng contract
         * @param amountForSale Amount of tokens for sale, set 0 to max out
         */
        function setTokenOffering(address offeringAddr, uint256 amountForSale) external onlyOwner onlyTokenOfferingAddrNotSet {
            require(!transferEnabled);
    
            uint256 amount = (amountForSale == 0) ? TOKEN_OFFERING_ALLOWANCE : amountForSale;
            require(amount <= TOKEN_OFFERING_ALLOWANCE);
    
            approve(offeringAddr, amount);
            tokenOfferingAddr = offeringAddr;
        }
        
        /**
         * Enable transfers
         */
        function enableTransfer() external onlyOwner {
            transferEnabled = true;
    
            // End the offering
            approve(tokenOfferingAddr, 0);
        }
    
        /**
         * Transfer from sender to another account
         *
         * @param to Destination address
         * @param value Amount of beetokens to send
         */
        function transfer(address to, uint256 value) public onlyWhenTransferAllowed validDestination(to) returns (bool) {
            return super.transfer(to, value);
        }
        
        /**
         * Transfer from `from` account to `to` account using allowance in `from` account to the sender
         *
         * @param from Origin address
         * @param to Destination address
         * @param value Amount of beetokens to send
         */
        function transferFrom(address from, address to, uint256 value) public onlyWhenTransferAllowed validDestination(to) returns (bool) {
            return super.transferFrom(from, to, value);
        }
        
        /**
         * Burn token, only owner is allowed to do this
         *
         * @param value Amount of tokens to burn
         */
        function burn(uint256 value) public {
            require(transferEnabled || msg.sender == owner);
            super.burn(value);
        }
    }
    
    contract BeeTokenOffering is Pausable {
        using SafeMath for uint256;
    
        // Start and end timestamps where contributions are allowed (both inclusive)
        uint256 public startTime;
        uint256 public endTime;
    
        // Address where funds are collected
        address public beneficiary;
    
        // Token to be sold
        BeeToken public token;
    
        // Price of the tokens as in tokens per ether
        uint256 public rate;
    
        // Amount of raised in Wei (1 ether)
        uint256 public weiRaised;
    
        // Timelines for different contribution limit policy
        uint256 public capDoublingTimestamp;
        uint256 public capReleaseTimestamp;
    
        // Individual contribution limits in Wei per tier
        uint256[3] public tierCaps;
    
        // Whitelists of participant address for each tier
        mapping(uint8 => mapping(address => bool)) public whitelists;
    
        // Contributions in Wei for each participant
        mapping(address => uint256) public contributions;
    
        // Funding cap in ETH. Change to equal $5M at time of token offering
        uint256 public constant FUNDING_ETH_HARD_CAP = 5000 * 1 ether;
    
        // Min contribution is 0.1 ether
        uint256 public constant MINIMUM_CONTRIBUTION = 10**17;
    
        // The current stage of the offering
        Stages public stage;
    
        enum Stages { 
            Setup,
            OfferingStarted,
            OfferingEnded
        }
    
        event OfferingOpens(uint256 startTime, uint256 endTime);
        event OfferingCloses(uint256 endTime, uint256 totalWeiRaised);
        /**
         * Event for token purchase logging
         *
         * @param purchaser Who paid for the tokens
         * @param value Weis paid for purchase
         * @return amount Amount of tokens purchased
         */
        event TokenPurchase(address indexed purchaser, uint256 value, uint256 amount);
    
        /**
         * Modifier that requires certain stage before executing the main function body
         *
         * @param expectedStage Value that the current stage is required to match
         */
        modifier atStage(Stages expectedStage) {
            require(stage == expectedStage);
            _;
        }
    
        /**
         * Modifier that validates a purchase at a tier
         * All the following has to be met:
         * - current time within the offering period
         * - valid sender address and ether value greater than 0.1
         * - total Wei raised not greater than FUNDING_ETH_HARD_CAP
         * - contribution per perticipant within contribution limit
         *
         * @param tier Index of the tier
         */
        modifier validPurchase(uint8 tier) {
            require(tier < tierCaps.length);
            require(now >= startTime && now <= endTime && stage == Stages.OfferingStarted);
    
            uint256 contributionInWei = msg.value;
            address participant = msg.sender;
            require(participant != address(0) && contributionInWei >= MINIMUM_CONTRIBUTION);
            require(weiRaised.add(contributionInWei) <= FUNDING_ETH_HARD_CAP);
    
            uint256 initialCapInWei = tierCaps[tier];
            
            if (now < capDoublingTimestamp) {
                require(contributions[participant].add(contributionInWei) <= initialCapInWei);
            } else if (now < capReleaseTimestamp) {
                require(contributions[participant].add(contributionInWei) <= initialCapInWei.mul(2));
            }
    
            _;
        }
    
        /**
         * The constructor of the contract.
         * Note: tierCaps[tier] define the individual contribution limits in Wei of each address
         * per tier within the first tranche of the sale (sale start ~ capDoublingTimestamp)
         * these limits are doubled between capDoublingTimestamp ~ capReleaseTimestamp
         * and are lifted completely between capReleaseTimestamp ~ end time
         *  
         * @param beeToEtherRate Number of beetokens per ether
         * @param beneficiaryAddr Address where funds are collected
         * @param baseContributionCapInWei Base contribution limit in Wei per address
         */
        function BeeTokenOffering(
            uint256 beeToEtherRate, 
            address beneficiaryAddr, 
            uint256 baseContributionCapInWei,
            address tokenAddress
        ) public {
            require(beeToEtherRate > 0);
            require(beneficiaryAddr != address(0));
            require(tokenAddress != address(0));
            require(baseContributionCapInWei >= MINIMUM_CONTRIBUTION);
    
            token = BeeToken(tokenAddress);
            rate = beeToEtherRate;
            beneficiary = beneficiaryAddr;
            stage = Stages.Setup;
    
            // Contribution cap per tier in Wei
            tierCaps[0] = baseContributionCapInWei.mul(3);
            tierCaps[1] = baseContributionCapInWei.mul(2);
            tierCaps[2] = baseContributionCapInWei;
        }
    
        /**
         * Fallback function can be used to buy tokens
         */
        function () public payable {
            buy();
        }
    
        /**
         * Withdraw available ethers into beneficiary account, serves as a safety, should never be needed
         */
        function ownerSafeWithdrawal() external onlyOwner {
            beneficiary.transfer(this.balance);
        }
    
        function updateRate(uint256 beeToEtherRate) public onlyOwner atStage(Stages.Setup) {
            rate = beeToEtherRate;
        }
    
        /**
         * Whitelist participant address per tier
         * 
         * @param tiers Array of indices of tier, each value should be less than tierCaps.length
         * @param users Array of addresses to be whitelisted
         */
        function whitelist(uint8[] tiers, address[] users) public onlyOwner {
            require(tiers.length == users.length);
            for (uint32 i = 0; i < users.length; i++) {
                require(tiers[i] < tierCaps.length);
                whitelists[tiers[i]][users[i]] = true;
            }
        }
    
        /**
         * Start the offering
         *
         * @param durationInSeconds Extra duration of the offering on top of the minimum 48 hours
         */
        function startOffering(uint256 durationInSeconds) public onlyOwner atStage(Stages.Setup) {
            stage = Stages.OfferingStarted;
            startTime = now;
            capDoublingTimestamp = startTime + 24 hours;
            capReleaseTimestamp = startTime + 48 hours;
            endTime = capReleaseTimestamp.add(durationInSeconds);
            OfferingOpens(startTime, endTime);
        }
    
        /**
         * End the offering
         */
        function endOffering() public onlyOwner atStage(Stages.OfferingStarted) {
            endOfferingImpl();
        }
        
        /**
         * Function to invest ether to buy tokens, can be called directly or called by the fallback function
         * Only whitelisted users can buy tokens.
         *
         * @return bool Return true if purchase succeeds, false otherwise
         */
        function buy() public payable whenNotPaused atStage(Stages.OfferingStarted) returns (bool) {
            for (uint8 i = 0; i < tierCaps.length; ++i) {
                if (whitelists[i][msg.sender]) {
                    buyTokensTier(i);
                    return true;
                }
            }
            revert();
        }
    
        /**
         * Function that returns whether offering has ended
         * 
         * @return bool Return true if token offering has ended
         */
        function hasEnded() public view returns (bool) {
            return now > endTime || stage == Stages.OfferingEnded;
        }
    
        /**
         * Internal function that buys token per tier
         * 
         * Investiment limit changes over time:
         * 1) [offering starts ~ capDoublingTimestamp]:     1x of contribution limit per tier (1 * tierCaps[tier])
         * 2) [capDoublingTimestamp ~ capReleaseTimestamp]: limit per participant is raised to 2x of contribution limit per tier (2 * tierCaps[tier])
         * 3) [capReleaseTimestamp ~ offering ends]:        no limit per participant as along as total Wei raised is within FUNDING_ETH_HARD_CAP
         *
         * @param tier Index of tier of whitelisted participant
         */
        function buyTokensTier(uint8 tier) internal validPurchase(tier) {
            address participant = msg.sender;
            uint256 contributionInWei = msg.value;
    
            // Calculate token amount to be distributed
            uint256 tokens = contributionInWei.mul(rate);
            
            if (!token.transferFrom(token.owner(), participant, tokens)) {
                revert();
            }
    
            weiRaised = weiRaised.add(contributionInWei);
            contributions[participant] = contributions[participant].add(contributionInWei);
            // Check if the funding cap has been reached, end the offering if so
            if (weiRaised >= FUNDING_ETH_HARD_CAP) {
                endOfferingImpl();
            }
            
            // Transfer funds to beneficiary
            beneficiary.transfer(contributionInWei);
            TokenPurchase(msg.sender, contributionInWei, tokens);       
        }
    
        /**
         * End token offering by set the stage and endTime
         */
        function endOfferingImpl() internal {
            endTime = now;
            stage = Stages.OfferingEnded;
            OfferingCloses(endTime, weiRaised);
        }
    
        /**
         * Allocate tokens for presale participants before public offering, can only be executed at Stages.Setup stage.
         *
         * @param to Participant address to send beetokens to
         * @param tokens Amount of beetokens to be sent to parcitipant 
         */
        function allocateTokensBeforeOffering(address to, uint256 tokens)
            public
            onlyOwner
            atStage(Stages.Setup)
            returns (bool)
        {
            if (!token.transferFrom(token.owner(), to, tokens)) {
                revert();
            }
            return true;
        }
        
        /**
         * Bulk version of allocateTokensBeforeOffering
         */
        function batchAllocateTokensBeforeOffering(address[] toList, uint256[] tokensList)
            external
            onlyOwner
            atStage(Stages.Setup)
            returns (bool)
        {
            require(toList.length == tokensList.length);
    
            for (uint32 i = 0; i < toList.length; i++) {
                allocateTokensBeforeOffering(toList[i], tokensList[i]);
            }
            return true;
        }
    
    }

    File 2 of 3: BeeToken
    pragma solidity ^0.4.18;
    
    /**
     * @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;
    
    
      event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    
    
      /**
       * @dev The Ownable constructor sets the original `owner` of the contract to the sender
       * account.
       */
      function Ownable() public {
        owner = msg.sender;
      }
    
    
      /**
       * @dev Throws if called by any account other than the owner.
       */
      modifier onlyOwner() {
        require(msg.sender == owner);
        _;
      }
    
    
      /**
       * @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) public onlyOwner {
        require(newOwner != address(0));
        OwnershipTransferred(owner, newOwner);
        owner = newOwner;
      }
    
    }
    
    /**
     * @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 make a function callable only when the contract is not paused.
       */
      modifier whenNotPaused() {
        require(!paused);
        _;
      }
    
      /**
       * @dev Modifier to make a function callable only when the contract is paused.
       */
      modifier whenPaused() {
        require(paused);
        _;
      }
    
      /**
       * @dev called by the owner to pause, triggers stopped state
       */
      function pause() onlyOwner whenNotPaused public {
        paused = true;
        Pause();
      }
    
      /**
       * @dev called by the owner to unpause, returns to normal state
       */
      function unpause() onlyOwner whenPaused public {
        paused = false;
        Unpause();
      }
    }
    
    /**
     * @title SafeMath
     * @dev Math operations with safety checks that throw on error
     */
    library SafeMath {
      function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) {
          return 0;
        }
        uint256 c = a * b;
        assert(c / a == b);
        return c;
      }
    
      function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // assert(b > 0); // Solidity automatically throws when dividing by 0
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold
        return c;
      }
    
      function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        assert(b <= a);
        return a - b;
      }
    
      function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        assert(c >= a);
        return c;
      }
    }
    
    /**
     * @title ERC20Basic
     * @dev Simpler version of ERC20 interface
     * @dev see https://github.com/ethereum/EIPs/issues/179
     */
    contract ERC20Basic {
      uint256 public totalSupply;
      function balanceOf(address who) public view returns (uint256);
      function transfer(address to, uint256 value) public returns (bool);
      event Transfer(address indexed from, address indexed to, uint256 value);
    }
    
    /**
     * @title ERC20 interface
     * @dev see https://github.com/ethereum/EIPs/issues/20
     */
    contract ERC20 is ERC20Basic {
      function allowance(address owner, address spender) public view returns (uint256);
      function transferFrom(address from, address to, uint256 value) public returns (bool);
      function approve(address spender, uint256 value) public returns (bool);
      event Approval(address indexed owner, address indexed spender, uint256 value);
    }
    
    /**
     * @title Basic token
     * @dev Basic version of StandardToken, with no allowances.
     */
    contract BasicToken is ERC20Basic {
      using SafeMath for uint256;
    
      mapping(address => uint256) balances;
    
      /**
      * @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, uint256 _value) public returns (bool) {
        require(_to != address(0));
        require(_value <= balances[msg.sender]);
    
        // SafeMath.sub will throw if there is not enough balance.
        balances[msg.sender] = balances[msg.sender].sub(_value);
        balances[_to] = balances[_to].add(_value);
        Transfer(msg.sender, _to, _value);
        return true;
      }
    
      /**
      * @dev Gets the balance of the specified address.
      * @param _owner The address to query the the balance of.
      * @return An uint256 representing the amount owned by the passed address.
      */
      function balanceOf(address _owner) public view returns (uint256 balance) {
        return balances[_owner];
      }
    
    }
    
    /**
     * @title Burnable Token
     * @dev Token that can be irreversibly burned (destroyed).
     */
    contract BurnableToken is BasicToken {
    
        event Burn(address indexed burner, uint256 value);
    
        /**
         * @dev Burns a specific amount of tokens.
         * @param _value The amount of token to be burned.
         */
        function burn(uint256 _value) public {
            require(_value <= balances[msg.sender]);
            // no need to require value <= totalSupply, since that would imply the
            // sender's balance is greater than the totalSupply, which *should* be an assertion failure
    
            address burner = msg.sender;
            balances[burner] = balances[burner].sub(_value);
            totalSupply = totalSupply.sub(_value);
            Burn(burner, _value);
        }
    }
    
    
    /**
     * @title Standard ERC20 token
     *
     * @dev Implementation of the basic standard 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 ERC20, BasicToken {
    
      mapping (address => mapping (address => uint256)) internal 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 uint256 the amount of tokens to be transferred
       */
      function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
        require(_to != address(0));
        require(_value <= balances[_from]);
        require(_value <= allowed[_from][msg.sender]);
    
        balances[_from] = balances[_from].sub(_value);
        balances[_to] = balances[_to].add(_value);
        allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
        Transfer(_from, _to, _value);
        return true;
      }
    
      /**
       * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
       *
       * Beware that changing an allowance with this method brings the risk that someone may use both the old
       * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
       * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
       * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
       * @param _spender The address which will spend the funds.
       * @param _value The amount of tokens to be spent.
       */
      function approve(address _spender, uint256 _value) public returns (bool) {
        allowed[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);
        return true;
      }
    
      /**
       * @dev Function to check the amount of tokens that 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 uint256 specifying the amount of tokens still available for the spender.
       */
      function allowance(address _owner, address _spender) public view returns (uint256) {
        return allowed[_owner][_spender];
      }
    
      /**
       * @dev Increase the amount of tokens that an owner allowed to a spender.
       *
       * approve should be called when allowed[_spender] == 0. To increment
       * allowed value is better to use this function to avoid 2 calls (and wait until
       * the first transaction is mined)
       * From MonolithDAO Token.sol
       * @param _spender The address which will spend the funds.
       * @param _addedValue The amount of tokens to increase the allowance by.
       */
      function increaseApproval(address _spender, uint _addedValue) public returns (bool) {
        allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue);
        Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
        return true;
      }
    
      /**
       * @dev Decrease the amount of tokens that an owner allowed to a spender.
       *
       * approve should be called when allowed[_spender] == 0. To decrement
       * allowed value is better to use this function to avoid 2 calls (and wait until
       * the first transaction is mined)
       * From MonolithDAO Token.sol
       * @param _spender The address which will spend the funds.
       * @param _subtractedValue The amount of tokens to decrease the allowance by.
       */
      function decreaseApproval(address _spender, uint _subtractedValue) public returns (bool) {
        uint oldValue = allowed[msg.sender][_spender];
        if (_subtractedValue > oldValue) {
          allowed[msg.sender][_spender] = 0;
        } else {
          allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);
        }
        Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
        return true;
      }
    
    }
    
    
    /*
     * BeeToken is a standard ERC20 token with some additional functionalities:
     * - Transfers are only enabled after contract owner enables it (after the ICO)
     * - Contract sets 30% of the total supply as allowance for ICO contract
     *
     * Note: Token Offering == Initial Coin Offering(ICO)
     */
    
    contract BeeToken is StandardToken, BurnableToken, Ownable {
        string public constant symbol = "BEE";
        string public constant name = "Bee Token";
        uint8 public constant decimals = 18;
        uint256 public constant INITIAL_SUPPLY = 500000000 * (10 ** uint256(decimals));
        uint256 public constant TOKEN_OFFERING_ALLOWANCE = 150000000 * (10 ** uint256(decimals));
        uint256 public constant ADMIN_ALLOWANCE = INITIAL_SUPPLY - TOKEN_OFFERING_ALLOWANCE;
        
        // Address of token admin
        address public adminAddr;
        // Address of token offering
        address public tokenOfferingAddr;
        // Enable transfers after conclusion of token offering
        bool public transferEnabled = false;
        
        /**
         * Check if transfer is allowed
         *
         * Permissions:
         *                                                       Owner    Admin    OffeirngContract    Others
         * transfer (before transferEnabled is true)               x        x            x               x
         * transferFrom (before transferEnabled is true)           x        v            v               x
         * transfer/transferFrom after transferEnabled is true     v        x            x               v
         */
        modifier onlyWhenTransferAllowed() {
            require(transferEnabled || msg.sender == adminAddr || msg.sender == tokenOfferingAddr);
            _;
        }
    
        /**
         * Check if token offering address is set or not
         */
        modifier onlyTokenOfferingAddrNotSet() {
            require(tokenOfferingAddr == address(0x0));
            _;
        }
    
        /**
         * Check if address is a valid destination to transfer tokens to
         * - must not be zero address
         * - must not be the token address
         * - must not be the owner's address
         * - must not be the admin's address
         * - must not be the token offering contract address
         */
        modifier validDestination(address to) {
            require(to != address(0x0));
            require(to != address(this));
            require(to != owner);
            require(to != address(adminAddr));
            require(to != address(tokenOfferingAddr));
            _;
        }
        
        /**
         * Token contract constructor
         *
         * @param admin Address of admin account
         */
        function BeeToken(address admin) public {
            totalSupply = INITIAL_SUPPLY;
            
            // Mint tokens
            balances[msg.sender] = totalSupply;
            Transfer(address(0x0), msg.sender, totalSupply);
    
            // Approve allowance for admin account
            adminAddr = admin;
            approve(adminAddr, ADMIN_ALLOWANCE);
        }
    
        /**
         * Set token offering to approve allowance for offering contract to distribute tokens
         *
         * @param offeringAddr Address of token offerng contract
         * @param amountForSale Amount of tokens for sale, set 0 to max out
         */
        function setTokenOffering(address offeringAddr, uint256 amountForSale) external onlyOwner onlyTokenOfferingAddrNotSet {
            require(!transferEnabled);
    
            uint256 amount = (amountForSale == 0) ? TOKEN_OFFERING_ALLOWANCE : amountForSale;
            require(amount <= TOKEN_OFFERING_ALLOWANCE);
    
            approve(offeringAddr, amount);
            tokenOfferingAddr = offeringAddr;
        }
        
        /**
         * Enable transfers
         */
        function enableTransfer() external onlyOwner {
            transferEnabled = true;
    
            // End the offering
            approve(tokenOfferingAddr, 0);
        }
    
        /**
         * Transfer from sender to another account
         *
         * @param to Destination address
         * @param value Amount of beetokens to send
         */
        function transfer(address to, uint256 value) public onlyWhenTransferAllowed validDestination(to) returns (bool) {
            return super.transfer(to, value);
        }
        
        /**
         * Transfer from `from` account to `to` account using allowance in `from` account to the sender
         *
         * @param from Origin address
         * @param to Destination address
         * @param value Amount of beetokens to send
         */
        function transferFrom(address from, address to, uint256 value) public onlyWhenTransferAllowed validDestination(to) returns (bool) {
            return super.transferFrom(from, to, value);
        }
        
        /**
         * Burn token, only owner is allowed to do this
         *
         * @param value Amount of tokens to burn
         */
        function burn(uint256 value) public {
            require(transferEnabled || msg.sender == owner);
            super.burn(value);
        }
    }
    
    contract BeeTokenOffering is Pausable {
        using SafeMath for uint256;
    
        // Start and end timestamps where contributions are allowed (both inclusive)
        uint256 public startTime;
        uint256 public endTime;
    
        // Address where funds are collected
        address public beneficiary;
    
        // Token to be sold
        BeeToken public token;
    
        // Price of the tokens as in tokens per ether
        uint256 public rate;
    
        // Amount of raised in Wei (1 ether)
        uint256 public weiRaised;
    
        // Timelines for different contribution limit policy
        uint256 public capDoublingTimestamp;
        uint256 public capReleaseTimestamp;
    
        // Individual contribution limits in Wei per tier
        uint256[3] public tierCaps;
    
        // Whitelists of participant address for each tier
        mapping(uint8 => mapping(address => bool)) public whitelists;
    
        // Contributions in Wei for each participant
        mapping(address => uint256) public contributions;
    
        // Funding cap in ETH. Change to equal $5M at time of token offering
        uint256 public constant FUNDING_ETH_HARD_CAP = 5000 * 1 ether;
    
        // The current stage of the offering
        Stages public stage;
    
        enum Stages { 
            Setup,
            OfferingStarted,
            OfferingEnded
        }
    
        event OfferingOpens(uint256 startTime, uint256 endTime);
        event OfferingCloses(uint256 endTime, uint256 totalWeiRaised);
        /**
         * Event for token purchase logging
         *
         * @param purchaser Who paid for the tokens
         * @param value Weis paid for purchase
         * @return amount Amount of tokens purchased
         */
        event TokenPurchase(address indexed purchaser, uint256 value, uint256 amount);
    
        /**
         * Modifier that requires certain stage before executing the main function body
         *
         * @param expectedStage Value that the current stage is required to match
         */
        modifier atStage(Stages expectedStage) {
            require(stage == expectedStage);
            _;
        }
    
        /**
         * Modifier that validates a purchase at a tier
         * All the following has to be met:
         * - current time within the offering period
         * - valid sender address and ether value greater than 0.1
         * - total Wei raised not greater than FUNDING_ETH_HARD_CAP
         * - contribution per perticipant within contribution limit
         *
         * @param tier Index of the tier
         */
        modifier validPurchase(uint8 tier) {
            require(tier < tierCaps.length);
            require(now >= startTime && now <= endTime && stage == Stages.OfferingStarted);
    
            uint256 contributionInWei = msg.value;
            address participant = msg.sender;
            require(participant != address(0) && contributionInWei > 100000000000000000);
            require(weiRaised.add(contributionInWei) <= FUNDING_ETH_HARD_CAP);
    
            uint256 initialCapInWei = tierCaps[tier];
            
            if (now < capDoublingTimestamp) {
                require(contributions[participant].add(contributionInWei) <= initialCapInWei);
            } else if (now < capReleaseTimestamp) {
                require(contributions[participant].add(contributionInWei) <= initialCapInWei.mul(2));
            }
    
            _;
        }
    
        /**
         * The constructor of the contract.
         * Note: tierCaps[tier] define the individual contribution limits in Wei of each address
         * per tier within the first tranche of the sale (sale start ~ capDoublingTimestamp)
         * these limits are doubled between capDoublingTimestamp ~ capReleaseTimestamp
         * and are lifted completely between capReleaseTimestamp ~ end time
         *  
         * @param beeToEtherRate Number of beetokens per ether
         * @param beneficiaryAddr Address where funds are collected
         * @param baseContributionCapInWei Base contribution limit in Wei per address
         */
        function BeeTokenOffering(
            uint256 beeToEtherRate, 
            address beneficiaryAddr, 
            uint256 baseContributionCapInWei,
            address tokenAddress
        ) public {
            require(beeToEtherRate > 0);
            require(beneficiaryAddr != address(0));
            require(tokenAddress != address(0));
    
            token = BeeToken(tokenAddress);
            rate = beeToEtherRate;
            beneficiary = beneficiaryAddr;
            stage = Stages.Setup;
    
            // Contribution cap per tier in Wei
            tierCaps[0] = baseContributionCapInWei.mul(3);
            tierCaps[1] = baseContributionCapInWei.mul(2);
            tierCaps[2] = baseContributionCapInWei;
        }
    
        /**
         * Fallback function can be used to buy tokens
         */
        function () public payable {
            buy();
        }
    
        /**
         * Withdraw available ethers into beneficiary account, serves as a safety, should never be needed
         */
        function ownerSafeWithdrawal() external onlyOwner {
            beneficiary.transfer(this.balance);
        }
    
        function updateRate(uint256 beeToEtherRate) public onlyOwner atStage(Stages.Setup) {
            rate = beeToEtherRate;
        }
    
        /**
         * Whitelist participant address per tier
         * 
         * @param tiers Array of indices of tier, each value should be less than tierCaps.length
         * @param users Array of addresses to be whitelisted
         */
        function whitelist(uint8[] tiers, address[] users) public onlyOwner {
            require(tiers.length == users.length);
            for (uint32 i = 0; i < users.length; i++) {
                require(tiers[i] < tierCaps.length);
                whitelists[tiers[i]][users[i]] = true;
            }
        }
    
        /**
         * Start the offering
         *
         * @param durationInSeconds Extra duration of the offering on top of the minimum 48 hours
         */
        function startOffering(uint256 durationInSeconds) public onlyOwner atStage(Stages.Setup) {
            stage = Stages.OfferingStarted;
            startTime = now;
            capDoublingTimestamp = startTime + 24 hours;
            capReleaseTimestamp = startTime + 48 hours;
            endTime = capReleaseTimestamp.add(durationInSeconds);
            OfferingOpens(startTime, endTime);
        }
    
        /**
         * End the offering
         */
        function endOffering() public onlyOwner atStage(Stages.OfferingStarted) {
            endOfferingImpl();
        }
        
        /**
         * Function to invest ether to buy tokens, can be called directly or called by the fallback function
         * Only whitelisted users can buy tokens.
         *
         * @return bool Return true if purchase succeeds, false otherwise
         */
        function buy() public payable whenNotPaused atStage(Stages.OfferingStarted) returns (bool) {
            for (uint8 i = 0; i < tierCaps.length; ++i) {
                if (whitelists[i][msg.sender]) {
                    buyTokensTier(i);
                    return true;
                }
            }
            revert();
        }
    
        /**
         * Function that returns whether offering has ended
         * 
         * @return bool Return true if token offering has ended
         */
        function hasEnded() public view returns (bool) {
            return now > endTime || stage == Stages.OfferingEnded;
        }
    
        /**
         * Internal function that buys token per tier
         * 
         * Investiment limit changes over time:
         * 1) [offering starts ~ capDoublingTimestamp]:     1x of contribution limit per tier (1 * tierCaps[tier])
         * 2) [capDoublingTimestamp ~ capReleaseTimestamp]: limit per participant is raised to 2x of contribution limit per tier (2 * tierCaps[tier])
         * 3) [capReleaseTimestamp ~ offering ends]:        no limit per participant as along as total Wei raised is within FUNDING_ETH_HARD_CAP
         *
         * @param tier Index of tier of whitelisted participant
         */
        function buyTokensTier(uint8 tier) internal validPurchase(tier) {
            address participant = msg.sender;
            uint256 contributionInWei = msg.value;
    
            // Calculate token amount to be distributed
            uint256 tokens = contributionInWei.mul(rate);
            
            if (!token.transferFrom(token.owner(), participant, tokens)) {
                revert();
            }
    
            weiRaised = weiRaised.add(contributionInWei);
            contributions[participant] = contributions[participant].add(contributionInWei);
            // Check if the funding cap has been reached, end the offering if so
            if (weiRaised >= FUNDING_ETH_HARD_CAP) {
                endOfferingImpl();
            }
            
            // Transfer funds to beneficiary
            beneficiary.transfer(contributionInWei);
            TokenPurchase(msg.sender, contributionInWei, tokens);       
        }
    
        /**
         * End token offering by set the stage and endTime
         */
        function endOfferingImpl() internal {
            endTime = now;
            stage = Stages.OfferingEnded;
            OfferingCloses(endTime, weiRaised);
        }
    
        /**
         * Allocate tokens for presale participants before public offering, can only be executed at Stages.Setup stage.
         *
         * @param to Participant address to send beetokens to
         * @param tokens Amount of beetokens to be sent to parcitipant 
         */
        function allocateTokensBeforeOffering(address to, uint256 tokens)
            public
            onlyOwner
            atStage(Stages.Setup)
            returns (bool)
        {
            if (!token.transferFrom(token.owner(), to, tokens)) {
                revert();
            }
            return true;
        }
        
        /**
         * Bulk version of allocateTokensBeforeOffering
         */
        function batchAllocateTokensBeforeOffering(address[] toList, uint256[] tokensList)
            external
            onlyOwner
            atStage(Stages.Setup)
            returns (bool)
        {
            require(toList.length == tokensList.length);
    
            for (uint32 i = 0; i < toList.length; i++) {
                allocateTokensBeforeOffering(toList[i], tokensList[i]);
            }
            return true;
        }
    
    }

    File 3 of 3: MultiSigWalletWithDailyLimit
    contract Factory {
    
        /*
         *  Events
         */
        event ContractInstantiation(address sender, address instantiation);
    
        /*
         *  Storage
         */
        mapping(address => bool) public isInstantiation;
        mapping(address => address[]) public instantiations;
    
        /*
         * Public functions
         */
        /// @dev Returns number of instantiations by creator.
        /// @param creator Contract creator.
        /// @return Returns number of instantiations by creator.
        function getInstantiationCount(address creator)
            public
            constant
            returns (uint)
        {
            return instantiations[creator].length;
        }
    
        /*
         * Internal functions
         */
        /// @dev Registers contract in factory registry.
        /// @param instantiation Address of contract instantiation.
        function register(address instantiation)
            internal
        {
            isInstantiation[instantiation] = true;
            instantiations[msg.sender].push(instantiation);
            ContractInstantiation(msg.sender, instantiation);
        }
    }
    
    /// @title Multisignature wallet - Allows multiple parties to agree on transactions before execution.
    /// @author Stefan George - <stefan.george@consensys.net>
    contract MultiSigWallet {
    
        /*
         *  Events
         */
        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);
    
        /*
         *  Constants
         */
        uint constant public MAX_OWNER_COUNT = 50;
    
        /*
         *  Storage
         */
        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;
        }
    
        /*
         *  Modifiers
         */
        modifier onlyWallet() {
            require(msg.sender == address(this));
            _;
        }
    
        modifier ownerDoesNotExist(address owner) {
            require(!isOwner[owner]);
            _;
        }
    
        modifier ownerExists(address owner) {
            require(isOwner[owner]);
            _;
        }
    
        modifier transactionExists(uint transactionId) {
            require(transactions[transactionId].destination != 0);
            _;
        }
    
        modifier confirmed(uint transactionId, address owner) {
            require(confirmations[transactionId][owner]);
            _;
        }
    
        modifier notConfirmed(uint transactionId, address owner) {
            require(!confirmations[transactionId][owner]);
            _;
        }
    
        modifier notExecuted(uint transactionId) {
            require(!transactions[transactionId].executed);
            _;
        }
    
        modifier notNull(address _address) {
            require(_address != 0);
            _;
        }
    
        modifier validRequirement(uint ownerCount, uint _required) {
            require(ownerCount <= MAX_OWNER_COUNT
                && _required <= ownerCount
                && _required != 0
                && ownerCount != 0);
            _;
        }
    
        /// @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++) {
                require(!isOwner[_owners[i]] && _owners[i] != 0);
                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 newOwner 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
            ownerExists(msg.sender)
            confirmed(transactionId, msg.sender)
            notExecuted(transactionId)
        {
            if (isConfirmed(transactionId)) {
                Transaction storage txn = transactions[transactionId];
                txn.executed = true;
                if (txn.destination.call.value(txn.value)(txn.data))
                    Execution(transactionId);
                else {
                    ExecutionFailure(transactionId);
                    txn.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 {
    
        /*
         *  Events
         */
        event DailyLimitChange(uint dailyLimit);
    
        /*
         *  Storage
         */
        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
            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 (txn.destination.call.value(txn.value)(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 || 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;
        }
    }