ETH Price: $2,053.22 (-3.98%)

Transaction Decoder

Block:
4276011 at Sep-15-2017 08:12:49 AM +UTC
Transaction Fee:
0.0009502 ETH $1.95
Gas Used:
95,020 Gas / 10 Gwei

Emitted Events:

139 MultiSigWalletWithDailyLimit.Deposit( sender=[Receiver] KyberNetworkTokenSale, value=3600000000000000000 )
140 KyberNetworkCrystal.Transfer( _from=[Receiver] KyberNetworkTokenSale, _to=[Sender] 0xfbd0d893d506c1d526e72422792e9266322fa37f, _value=2160000000000000000000 )
141 KyberNetworkTokenSale.Buy( _buyer=[Sender] 0xfbd0d893d506c1d526e72422792e9266322fa37f, _tokens=2160000000000000000000, _payedWei=3600000000000000000 )

Account State Difference:

  Address   Before After State Difference Code
0x3EB01B33...eC596F650
(Kyber: MultiSig)
38,973.745341818933102966 Eth38,977.345341818933102966 Eth3.6
(Nanopool)
8,323.17432806000335801 Eth8,323.17527826000335801 Eth0.0009502
0xd6Cd31F2...c07C15792
(Kyber: Token Sale)
0xdd974D5C...6686BD200
0xFbd0D893...6322fA37f
3.61 Eth
Nonce: 0
0.0090498 Eth
Nonce: 1
3.6009502

Execution Trace

ETH 3.6 KyberNetworkTokenSale.CALL( )
  • KyberContributorWhitelist.getCap( _user=0xFbd0D893d506c1D526E72422792E9266322fA37f ) => ( 3600000000000000000 )
  • ETH 3.6 MultiSigWalletWithDailyLimit.CALL( )
  • KyberNetworkCrystal.transfer( _to=0xFbd0D893d506c1D526E72422792E9266322fA37f, _value=2160000000000000000000 ) => ( True )
    File 1 of 4: KyberNetworkTokenSale
    pragma solidity ^0.4.13;
    
    library SafeMath {
      function mul(uint256 a, uint256 b) internal constant returns (uint256) {
        uint256 c = a * b;
        assert(a == 0 || c / a == b);
        return c;
      }
    
      function div(uint256 a, uint256 b) internal constant 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 constant returns (uint256) {
        assert(b <= a);
        return a - b;
      }
    
      function add(uint256 a, uint256 b) internal constant returns (uint256) {
        uint256 c = a + b;
        assert(c >= a);
        return c;
      }
    }
    
    contract ContributorApprover {
        KyberContributorWhitelist public list;
        mapping(address=>uint)    public participated;
    
        uint                      public cappedSaleStartTime;
        uint                      public openSaleStartTime;
        uint                      public openSaleEndTime;
    
        using SafeMath for uint;
    
    
        function ContributorApprover( KyberContributorWhitelist _whitelistContract,
                                      uint                      _cappedSaleStartTime,
                                      uint                      _openSaleStartTime,
                                      uint                      _openSaleEndTime ) {
            list = _whitelistContract;
            cappedSaleStartTime = _cappedSaleStartTime;
            openSaleStartTime = _openSaleStartTime;
            openSaleEndTime = _openSaleEndTime;
    
            require( list != KyberContributorWhitelist(0x0) );
            require( cappedSaleStartTime < openSaleStartTime );
            require(  openSaleStartTime < openSaleEndTime );
        }
    
        // this is a seperate function so user could query it before crowdsale starts
        function contributorCap( address contributor ) constant returns(uint) {
            return list.getCap( contributor );
        }
    
        function eligible( address contributor, uint amountInWei ) constant returns(uint) {
            if( now < cappedSaleStartTime ) return 0;
            if( now >= openSaleEndTime ) return 0;
    
            uint cap = contributorCap( contributor );
    
            if( cap == 0 ) return 0;
            if( now < openSaleStartTime ) {
                uint remainedCap = cap.sub( participated[ contributor ] );
    
                if( remainedCap > amountInWei ) return amountInWei;
                else return remainedCap;
            }
            else {
                return amountInWei;
            }
        }
    
        function eligibleTestAndIncrement( address contributor, uint amountInWei ) internal returns(uint) {
            uint result = eligible( contributor, amountInWei );
            participated[contributor] = participated[contributor].add( result );
    
            return result;
        }
    
        function saleEnded() constant returns(bool) {
            return now > openSaleEndTime;
        }
    
        function saleStarted() constant returns(bool) {
            return now >= cappedSaleStartTime;
        }
    }
    
    contract KyberNetworkTokenSale is ContributorApprover {
        address             public admin;
        address             public kyberMultiSigWallet;
        KyberNetworkCrystal public token;
        uint                public raisedWei;
        bool                public haltSale;
    
        mapping(bytes32=>uint) public proxyPurchases;
    
        function KyberNetworkTokenSale( address _admin,
                                        address _kyberMultiSigWallet,
                                        KyberContributorWhitelist _whilteListContract,
                                        uint _totalTokenSupply,
                                        uint _premintedTokenSupply,
                                        uint _cappedSaleStartTime,
                                        uint _publicSaleStartTime,
                                        uint _publicSaleEndTime )
    
            ContributorApprover( _whilteListContract,
                                 _cappedSaleStartTime,
                                 _publicSaleStartTime,
                                 _publicSaleEndTime )
        {
            admin = _admin;
            kyberMultiSigWallet = _kyberMultiSigWallet;
    
            token = new KyberNetworkCrystal( _totalTokenSupply,
                                             _cappedSaleStartTime,
                                             _publicSaleEndTime + 7 days,
                                             _admin );
    
            // transfer preminted tokens to company wallet
            token.transfer( kyberMultiSigWallet, _premintedTokenSupply );
        }
    
        function setHaltSale( bool halt ) {
            require( msg.sender == admin );
            haltSale = halt;
        }
    
        function() payable {
            buy( msg.sender );
        }
    
        event ProxyBuy( bytes32 indexed _proxy, address _recipient, uint _amountInWei );
        function proxyBuy( bytes32 proxy, address recipient ) payable returns(uint){
            uint amount = buy( recipient );
            proxyPurchases[proxy] = proxyPurchases[proxy].add(amount);
            ProxyBuy( proxy, recipient, amount );
    
            return amount;
        }
    
        event Buy( address _buyer, uint _tokens, uint _payedWei );
        function buy( address recipient ) payable returns(uint){
            require( tx.gasprice <= 50000000000 wei );
    
            require( ! haltSale );
            require( saleStarted() );
            require( ! saleEnded() );
    
            uint weiPayment = eligibleTestAndIncrement( recipient, msg.value );
    
            require( weiPayment > 0 );
    
            // send to msg.sender, not to recipient
            if( msg.value > weiPayment ) {
                msg.sender.transfer( msg.value.sub( weiPayment ) );
            }
    
            // send payment to wallet
            sendETHToMultiSig( weiPayment );
            raisedWei = raisedWei.add( weiPayment );
            uint recievedTokens = weiPayment.mul( 600 );
    
            assert( token.transfer( recipient, recievedTokens ) );
    
    
            Buy( recipient, recievedTokens, weiPayment );
    
            return weiPayment;
        }
    
        function sendETHToMultiSig( uint value ) internal {
            kyberMultiSigWallet.transfer( value );
        }
    
        event FinalizeSale();
        // function is callable by everyone
        function finalizeSale() {
            require( saleEnded() );
            require( msg.sender == admin );
    
            // burn remaining tokens
            token.burn(token.balanceOf(this));
    
            FinalizeSale();
        }
    
        // ETH balance is always expected to be 0.
        // but in case something went wrong, we use this function to extract the eth.
        function emergencyDrain(ERC20 anyToken) returns(bool){
            require( msg.sender == admin );
            require( saleEnded() );
    
            if( this.balance > 0 ) {
                sendETHToMultiSig( this.balance );
            }
    
            if( anyToken != address(0x0) ) {
                assert( anyToken.transfer(kyberMultiSigWallet, anyToken.balanceOf(this)) );
            }
    
            return true;
        }
    
        // just to check that funds goes to the right place
        // tokens are not given in return
        function debugBuy() payable {
            require( msg.value == 123 );
            sendETHToMultiSig( msg.value );
        }
    }
    
    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() {
        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) onlyOwner {
        if (newOwner != address(0)) {
          owner = newOwner;
        }
      }
    
    }
    
    contract KyberContributorWhitelist is Ownable {
        // cap is in wei. The value of 7 is just a stub.
        // after kyc registration ends, we change it to the actual value with setSlackUsersCap
        uint public slackUsersCap = 7;
        mapping(address=>uint) public addressCap;
    
        function KyberContributorWhitelist() {}
    
        event ListAddress( address _user, uint _cap, uint _time );
    
        // Owner can delist by setting cap = 0.
        // Onwer can also change it at any time
        function listAddress( address _user, uint _cap ) onlyOwner {
            addressCap[_user] = _cap;
            ListAddress( _user, _cap, now );
        }
    
        // an optimization in case of network congestion
        function listAddresses( address[] _users, uint[] _cap ) onlyOwner {
            require(_users.length == _cap.length );
            for( uint i = 0 ; i < _users.length ; i++ ) {
                listAddress( _users[i], _cap[i] );
            }
        }
    
        function setSlackUsersCap( uint _cap ) onlyOwner {
            slackUsersCap = _cap;
        }
    
        function getCap( address _user ) constant returns(uint) {
            uint cap = addressCap[_user];
    
            if( cap == 1 ) return slackUsersCap;
            else return cap;
        }
    
        function destroy() onlyOwner {
            selfdestruct(owner);
        }
    }
    
    contract ERC20Basic {
      uint256 public totalSupply;
      function balanceOf(address who) constant returns (uint256);
      function transfer(address to, uint256 value) returns (bool);
      
      // KYBER-NOTE! code changed to comply with ERC20 standard
      event Transfer(address indexed _from, address indexed _to, uint _value);
      //event Transfer(address indexed from, address indexed to, uint256 value);
    }
    
    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) returns (bool) {
        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) constant returns (uint256 balance) {
        return balances[_owner];
      }
    
    }
    
    contract ERC20 is ERC20Basic {
      function allowance(address owner, address spender) constant returns (uint256);
      function transferFrom(address from, address to, uint256 value) returns (bool);
      function approve(address spender, uint256 value) returns (bool);
      
      // KYBER-NOTE! code changed to comply with ERC20 standard
      event Approval(address indexed _owner, address indexed _spender, uint _value);
      //event Approval(address indexed owner, address indexed spender, uint256 value);
    }
    
    contract StandardToken is ERC20, BasicToken {
    
      mapping (address => mapping (address => uint256)) 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 amout of tokens to be transfered
       */
      function transferFrom(address _from, address _to, uint256 _value) returns (bool) {
        var _allowance = allowed[_from][msg.sender];
    
        // Check is not needed because sub(_allowance, _value) will already throw if this condition is not met
        // require (_value <= _allowance);
    
        // KYBER-NOTE! code changed to comply with ERC20 standard
        balances[_from] = balances[_from].sub(_value);
        balances[_to] = balances[_to].add(_value);
        //balances[_from] = balances[_from].sub(_value); // this was removed
        allowed[_from][msg.sender] = _allowance.sub(_value);
        Transfer(_from, _to, _value);
        return true;
      }
    
      /**
       * @dev Aprove the passed address to spend the specified amount of tokens on behalf 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, uint256 _value) returns (bool) {
    
        // To change the approve amount you first have to reduce the addresses`
        //  allowance to zero by calling `approve(_spender, 0)` if it is not
        //  already 0 to mitigate the race condition described here:
        //  https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
        require((_value == 0) || (allowed[msg.sender][_spender] == 0));
    
        allowed[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);
        return true;
      }
    
      /**
       * @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 specifing the amount of tokens still avaible for the spender.
       */
      function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
        return allowed[_owner][_spender];
      }
    
    }
    
    contract KyberNetworkCrystal is StandardToken, Ownable {
        string  public  constant name = "Kyber Network Crystal";
        string  public  constant symbol = "KNC";
        uint    public  constant decimals = 18;
    
        uint    public  saleStartTime;
        uint    public  saleEndTime;
    
        address public  tokenSaleContract;
    
        modifier onlyWhenTransferEnabled() {
            if( now <= saleEndTime && now >= saleStartTime ) {
                require( msg.sender == tokenSaleContract );
            }
            _;
        }
    
        modifier validDestination( address to ) {
            require(to != address(0x0));
            require(to != address(this) );
            _;
        }
    
        function KyberNetworkCrystal( uint tokenTotalAmount, uint startTime, uint endTime, address admin ) {
            // Mint all tokens. Then disable minting forever.
            balances[msg.sender] = tokenTotalAmount;
            totalSupply = tokenTotalAmount;
            Transfer(address(0x0), msg.sender, tokenTotalAmount);
    
            saleStartTime = startTime;
            saleEndTime = endTime;
    
            tokenSaleContract = msg.sender;
            transferOwnership(admin); // admin could drain tokens that were sent here by mistake
        }
    
        function transfer(address _to, uint _value)
            onlyWhenTransferEnabled
            validDestination(_to)
            returns (bool) {
            return super.transfer(_to, _value);
        }
    
        function transferFrom(address _from, address _to, uint _value)
            onlyWhenTransferEnabled
            validDestination(_to)
            returns (bool) {
            return super.transferFrom(_from, _to, _value);
        }
    
        event Burn(address indexed _burner, uint _value);
    
        function burn(uint _value) onlyWhenTransferEnabled
            returns (bool){
            balances[msg.sender] = balances[msg.sender].sub(_value);
            totalSupply = totalSupply.sub(_value);
            Burn(msg.sender, _value);
            Transfer(msg.sender, address(0x0), _value);
            return true;
        }
    
        // save some gas by making only one contract call
        function burnFrom(address _from, uint256 _value) onlyWhenTransferEnabled
            returns (bool) {
            assert( transferFrom( _from, msg.sender, _value ) );
            return burn(_value);
        }
    
        function emergencyERC20Drain( ERC20 token, uint amount ) onlyOwner {
            token.transfer( owner, amount );
        }
    }

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

    File 3 of 4: KyberNetworkCrystal
    pragma solidity ^0.4.13;
    
    library SafeMath {
      function mul(uint256 a, uint256 b) internal constant returns (uint256) {
        uint256 c = a * b;
        assert(a == 0 || c / a == b);
        return c;
      }
    
      function div(uint256 a, uint256 b) internal constant 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 constant returns (uint256) {
        assert(b <= a);
        return a - b;
      }
    
      function add(uint256 a, uint256 b) internal constant returns (uint256) {
        uint256 c = a + b;
        assert(c >= a);
        return c;
      }
    }
    
    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() {
        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) onlyOwner {
        if (newOwner != address(0)) {
          owner = newOwner;
        }
      }
    
    }
    
    
    
    contract ERC20Basic {
      uint256 public totalSupply;
      function balanceOf(address who) constant returns (uint256);
      function transfer(address to, uint256 value) returns (bool);
      
      // KYBER-NOTE! code changed to comply with ERC20 standard
      event Transfer(address indexed _from, address indexed _to, uint _value);
      //event Transfer(address indexed from, address indexed to, uint256 value);
    }
    
    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) returns (bool) {
        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) constant returns (uint256 balance) {
        return balances[_owner];
      }
    
    }
    
    contract ERC20 is ERC20Basic {
      function allowance(address owner, address spender) constant returns (uint256);
      function transferFrom(address from, address to, uint256 value) returns (bool);
      function approve(address spender, uint256 value) returns (bool);
      
      // KYBER-NOTE! code changed to comply with ERC20 standard
      event Approval(address indexed _owner, address indexed _spender, uint _value);
      //event Approval(address indexed owner, address indexed spender, uint256 value);
    }
    
    contract StandardToken is ERC20, BasicToken {
    
      mapping (address => mapping (address => uint256)) 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 amout of tokens to be transfered
       */
      function transferFrom(address _from, address _to, uint256 _value) returns (bool) {
        var _allowance = allowed[_from][msg.sender];
    
        // Check is not needed because sub(_allowance, _value) will already throw if this condition is not met
        // require (_value <= _allowance);
    
        // KYBER-NOTE! code changed to comply with ERC20 standard
        balances[_from] = balances[_from].sub(_value);
        balances[_to] = balances[_to].add(_value);
        //balances[_from] = balances[_from].sub(_value); // this was removed
        allowed[_from][msg.sender] = _allowance.sub(_value);
        Transfer(_from, _to, _value);
        return true;
      }
    
      /**
       * @dev Aprove the passed address to spend the specified amount of tokens on behalf 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, uint256 _value) returns (bool) {
    
        // To change the approve amount you first have to reduce the addresses`
        //  allowance to zero by calling `approve(_spender, 0)` if it is not
        //  already 0 to mitigate the race condition described here:
        //  https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
        require((_value == 0) || (allowed[msg.sender][_spender] == 0));
    
        allowed[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);
        return true;
      }
    
      /**
       * @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 specifing the amount of tokens still avaible for the spender.
       */
      function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
        return allowed[_owner][_spender];
      }
    
    }
    
    contract KyberNetworkCrystal is StandardToken, Ownable {
        string  public  constant name = "Kyber Network Crystal";
        string  public  constant symbol = "KNC";
        uint    public  constant decimals = 18;
    
        uint    public  saleStartTime;
        uint    public  saleEndTime;
    
        address public  tokenSaleContract;
    
        modifier onlyWhenTransferEnabled() {
            if( now <= saleEndTime && now >= saleStartTime ) {
                require( msg.sender == tokenSaleContract );
            }
            _;
        }
    
        modifier validDestination( address to ) {
            require(to != address(0x0));
            require(to != address(this) );
            _;
        }
    
        function KyberNetworkCrystal( uint tokenTotalAmount, uint startTime, uint endTime, address admin ) {
            // Mint all tokens. Then disable minting forever.
            balances[msg.sender] = tokenTotalAmount;
            totalSupply = tokenTotalAmount;
            Transfer(address(0x0), msg.sender, tokenTotalAmount);
    
            saleStartTime = startTime;
            saleEndTime = endTime;
    
            tokenSaleContract = msg.sender;
            transferOwnership(admin); // admin could drain tokens that were sent here by mistake
        }
    
        function transfer(address _to, uint _value)
            onlyWhenTransferEnabled
            validDestination(_to)
            returns (bool) {
            return super.transfer(_to, _value);
        }
    
        function transferFrom(address _from, address _to, uint _value)
            onlyWhenTransferEnabled
            validDestination(_to)
            returns (bool) {
            return super.transferFrom(_from, _to, _value);
        }
    
        event Burn(address indexed _burner, uint _value);
    
        function burn(uint _value) onlyWhenTransferEnabled
            returns (bool){
            balances[msg.sender] = balances[msg.sender].sub(_value);
            totalSupply = totalSupply.sub(_value);
            Burn(msg.sender, _value);
            Transfer(msg.sender, address(0x0), _value);
            return true;
        }
    
        // save some gas by making only one contract call
        function burnFrom(address _from, uint256 _value) onlyWhenTransferEnabled
            returns (bool) {
            assert( transferFrom( _from, msg.sender, _value ) );
            return burn(_value);
        }
    
        function emergencyERC20Drain( ERC20 token, uint amount ) onlyOwner {
            token.transfer( owner, amount );
        }
    }

    File 4 of 4: KyberContributorWhitelist
    pragma solidity ^0.4.13;
    
    
    /**
     * @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() {
        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) onlyOwner {
        if (newOwner != address(0)) {
          owner = newOwner;
        }
      }
    
    }
    
    contract KyberContributorWhitelist is Ownable {
        // 7 wei is a dummy cap. Will be set by owner to a real cap after registration ends.
        uint public slackUsersCap = 7;
        mapping(address=>uint) public addressCap;
    
        function KyberContributorWhitelist() {}
    
        event ListAddress( address _user, uint _cap, uint _time );
    
        // Owner can delist by setting cap = 0.
        // Onwer can also change it at any time
        function listAddress( address _user, uint _cap ) onlyOwner {
            addressCap[_user] = _cap;
            ListAddress( _user, _cap, now );
        }
    
        // an optimasition in case of network congestion
        function listAddresses( address[] _users, uint[] _cap ) onlyOwner {
            require(_users.length == _cap.length );
            for( uint i = 0 ; i < _users.length ; i++ ) {
                listAddress( _users[i], _cap[i] );
            }
        }
    
        function setSlackUsersCap( uint _cap ) onlyOwner {
            slackUsersCap = _cap;
        }
    
        function getCap( address _user ) constant returns(uint) {
            uint cap = addressCap[_user];
    
            if( cap == 1 ) return slackUsersCap;
            else return cap;
        }
    
        function destroy() onlyOwner {
            selfdestruct(owner);
        }
    }