ETH Price: $1,979.13 (+0.13%)

Transaction Decoder

Block:
3471742 at Apr-03-2017 09:47:47 PM +UTC
Transaction Fee:
0.00145134 ETH $2.87
Gas Used:
72,567 Gas / 20 Gwei

Emitted Events:

0 Wallet.Deposit( _from=[Receiver] Contribution, value=664000000000000000000 )
1 Contribution.Buy( _recipient=[Sender] 0x0023f04c87272874560ae330004a47db361b1ff3, _amount=292160000 )

Account State Difference:

  Address   Before After State Difference Code
0x0023f04C...B361B1FF3
1,000 Eth
Nonce: 0
335.99854866 Eth
Nonce: 1
664.00145134
(Ethpool 2)
340.115826478496069506 Eth340.117277818496069506 Eth0.00145134
0x72a7197b...06017768A
(MatchPoolWallet)
111,838.965672726487344858 Eth112,502.965672726487344858 Eth664
0xE05CeDD2...F2a10F729
(MatchPool: Token Sale)
0xf7B09829...60792894C

Execution Trace

ETH 664 Contribution.CALL( )
  • ETH 664 Wallet.CALL( )
  • GUPToken.createToken( _recipient=0x0023f04C87272874560Ae330004A47DB361B1FF3, _value=292160000 ) => ( o_success=True )
    File 1 of 3: Contribution
    pragma solidity ^0.4.8;
    
    
    contract SafeMath {
    
      function assert(bool assertion) internal {
        if (!assertion) throw;
      }
    
      function safeMul(uint a, uint b) internal returns (uint) {
        uint c = a * b;
        assert(a == 0 || c / a == b);
        return c;
      }
    
      function safeDiv(uint a, uint b) internal returns (uint) {
        assert(b > 0);
        uint c = a / b;
        assert(a == b * c + a % b);
        return c;
      }
    
    }
    
    
    contract StandardTokenProtocol {
    
        function totalSupply() constant returns (uint256 totalSupply) {}
        function balanceOf(address _owner) constant returns (uint256 balance) {}
        function transfer(address _recipient, uint256 _value) returns (bool success) {}
        function transferFrom(address _from, address _recipient, uint256 _value) returns (bool success) {}
        function approve(address _spender, uint256 _value) returns (bool success) {}
        function allowance(address _owner, address _spender) constant returns (uint256 remaining) {}
    
        event Transfer(address indexed _from, address indexed _recipient, uint256 _value);
        event Approval(address indexed _owner, address indexed _spender, uint256 _value);
    
    }
    
    
    contract StandardToken is StandardTokenProtocol {
    
        modifier when_can_transfer(address _from, uint256 _value) {
            if (balances[_from] >= _value) _;
        }
    
        modifier when_can_receive(address _recipient, uint256 _value) {
            if (balances[_recipient] + _value > balances[_recipient]) _;
        }
    
        modifier when_is_allowed(address _from, address _delegate, uint256 _value) {
            if (allowed[_from][_delegate] >= _value) _;
        }
    
        function transfer(address _recipient, uint256 _value)
            when_can_transfer(msg.sender, _value)
            when_can_receive(_recipient, _value)
            returns (bool o_success)
        {
            balances[msg.sender] -= _value;
            balances[_recipient] += _value;
            Transfer(msg.sender, _recipient, _value);
            return true;
        }
    
        function transferFrom(address _from, address _recipient, uint256 _value)
            when_can_transfer(_from, _value)
            when_can_receive(_recipient, _value)
            when_is_allowed(_from, msg.sender, _value)
            returns (bool o_success)
        {
            allowed[_from][msg.sender] -= _value;
            balances[_from] -= _value;
            balances[_recipient] += _value;
            Transfer(_from, _recipient, _value);
            return true;
        }
    
        function balanceOf(address _owner) constant returns (uint256 balance) {
            return balances[_owner];
        }
    
        function approve(address _spender, uint256 _value) returns (bool o_success) {
            allowed[msg.sender][_spender] = _value;
            Approval(msg.sender, _spender, _value);
            return true;
        }
    
        function allowance(address _owner, address _spender) constant returns (uint256 o_remaining) {
            return allowed[_owner][_spender];
        }
    
        mapping (address => uint256) balances;
        mapping (address => mapping (address => uint256)) allowed;
        uint256 public totalSupply;
    
    }
    
    contract GUPToken is StandardToken {
    
    	//FIELDS
    	string public name = "Guppy";
        string public symbol = "GUP";
        uint public decimals = 3;
    
    	//CONSTANTS
    	uint public constant LOCKOUT_PERIOD = 1 years; //time after end date that illiquid GUP can be transferred
    
    	//ASSIGNED IN INITIALIZATION
    	uint public endMintingTime; //Timestamp after which no more tokens can be created
    	address public minter; //address of the account which may mint new tokens
    
    	mapping (address => uint) public illiquidBalance; //Balance of 'Frozen funds'
    
    	//MODIFIERS
    	//Can only be called by contribution contract.
    	modifier only_minter {
    		if (msg.sender != minter) throw;
    		_;
    	}
    
    	// Can only be called if illiquid tokens may be transformed into liquid.
    	// This happens when `LOCKOUT_PERIOD` of time passes after `endMintingTime`.
    	modifier when_thawable {
    		if (now < endMintingTime + LOCKOUT_PERIOD) throw;
    		_;
    	}
    
    	// Can only be called if (liquid) tokens may be transferred. Happens
    	// immediately after `endMintingTime`.
    	modifier when_transferable {
    		if (now < endMintingTime) throw;
    		_;
    	}
    
    	// Can only be called if the `crowdfunder` is allowed to mint tokens. Any
    	// time before `endMintingTime`.
    	modifier when_mintable {
    		if (now >= endMintingTime) throw;
    		_;
    	}
    
    	// Initialization contract assigns address of crowdfund contract and end time.
    	function GUPToken(address _minter, uint _endMintingTime) {
    		endMintingTime = _endMintingTime;
    		minter = _minter;
    	}
    
    	// Create new tokens when called by the crowdfund contract.
    	// Only callable before the end time.
    	function createToken(address _recipient, uint _value)
    		when_mintable
    		only_minter
    		returns (bool o_success)
    	{
    		balances[_recipient] += _value;
    		totalSupply += _value;
    		return true;
    	}
    
    	// Create an illiquidBalance which cannot be traded until end of lockout period.
    	// Can only be called by crowdfund contract before the end time.
    	function createIlliquidToken(address _recipient, uint _value)
    		when_mintable
    		only_minter
    		returns (bool o_success)
    	{
    		illiquidBalance[_recipient] += _value;
    		totalSupply += _value;
    		return true;
    	}
    
    	// Make sender's illiquid balance liquid when called after lockout period.
    	function makeLiquid()
    		when_thawable
    	{
    		balances[msg.sender] += illiquidBalance[msg.sender];
    		illiquidBalance[msg.sender] = 0;
    	}
    
    	// Transfer amount of tokens from sender account to recipient.
    	// Only callable after the crowd fund end date.
    	function transfer(address _recipient, uint _amount)
    		when_transferable
    		returns (bool o_success)
    	{
    		return super.transfer(_recipient, _amount);
    	}
    
    	// Transfer amount of tokens from a specified address to a recipient.
    	// Only callable after the crowd fund end date.
    	function transferFrom(address _from, address _recipient, uint _amount)
    		when_transferable
    		returns (bool o_success)
    	{
    		return super.transferFrom(_from, _recipient, _amount);
    	}
    }
    
    
    contract Contribution is SafeMath {
    
    	//FIELDS
    
    	//CONSTANTS
    	//Time limits
    	uint public constant STAGE_ONE_TIME_END = 5 hours;
    	uint public constant STAGE_TWO_TIME_END = 72 hours;
    	uint public constant STAGE_THREE_TIME_END = 2 weeks;
    	uint public constant STAGE_FOUR_TIME_END = 4 weeks;
    	//Prices of GUP
    	uint public constant PRICE_STAGE_ONE   = 480000;
    	uint public constant PRICE_STAGE_TWO   = 440000;
    	uint public constant PRICE_STAGE_THREE = 400000;
    	uint public constant PRICE_STAGE_FOUR  = 360000;
    	uint public constant PRICE_BTCS        = 480000;
    	//GUP Token Limits
    	uint public constant MAX_SUPPLY =        100000000000;
    	uint public constant ALLOC_ILLIQUID_TEAM = 8000000000;
    	uint public constant ALLOC_LIQUID_TEAM =  13000000000;
    	uint public constant ALLOC_BOUNTIES =      2000000000;
    	uint public constant ALLOC_NEW_USERS =    17000000000;
    	uint public constant ALLOC_CROWDSALE =    60000000000;
    	uint public constant BTCS_PORTION_MAX = 31250 * PRICE_BTCS;
    	//ASSIGNED IN INITIALIZATION
    	//Start and end times
    	uint public publicStartTime; //Time in seconds public crowd fund starts.
    	uint public privateStartTime; //Time in seconds when BTCSuisse can purchase up to 31250 ETH worth of GUP;
    	uint public publicEndTime; //Time in seconds crowdsale ends
    	//Special Addresses
    	address public btcsAddress; //Address used by BTCSuisse
    	address public multisigAddress; //Address to which all ether flows.
    	address public matchpoolAddress; //Address to which ALLOC_BOUNTIES, ALLOC_LIQUID_TEAM, ALLOC_NEW_USERS, ALLOC_ILLIQUID_TEAM is sent to.
    	address public ownerAddress; //Address of the contract owner. Can halt the crowdsale.
    	//Contracts
    	GUPToken public gupToken; //External token contract hollding the GUP
    	//Running totals
    	uint public etherRaised; //Total Ether raised.
    	uint public gupSold; //Total GUP created
    	uint public btcsPortionTotal; //Total of Tokens purchased by BTC Suisse. Not to exceed BTCS_PORTION_MAX.
    	//booleans
    	bool public halted; //halts the crowd sale if true.
    
    	//FUNCTION MODIFIERS
    
    	//Is currently in the period after the private start time and before the public start time.
    	modifier is_pre_crowdfund_period() {
    		if (now >= publicStartTime || now < privateStartTime) throw;
    		_;
    	}
    
    	//Is currently the crowdfund period
    	modifier is_crowdfund_period() {
    		if (now < publicStartTime || now >= publicEndTime) throw;
    		_;
    	}
    
    	//May only be called by BTC Suisse
    	modifier only_btcs() {
    		if (msg.sender != btcsAddress) throw;
    		_;
    	}
    
    	//May only be called by the owner address
    	modifier only_owner() {
    		if (msg.sender != ownerAddress) throw;
    		_;
    	}
    
    	//May only be called if the crowdfund has not been halted
    	modifier is_not_halted() {
    		if (halted) throw;
    		_;
    	}
    
    	// EVENTS
    
    	event PreBuy(uint _amount);
    	event Buy(address indexed _recipient, uint _amount);
    
    
    	// FUNCTIONS
    
    	//Initialization function. Deploys GUPToken contract assigns values, to all remaining fields, creates first entitlements in the GUP Token contract.
    	function Contribution(
    		address _btcs,
    		address _multisig,
    		address _matchpool,
    		uint _publicStartTime,
    		uint _privateStartTime
    	) {
    		ownerAddress = msg.sender;
    		publicStartTime = _publicStartTime;
    		privateStartTime = _privateStartTime;
    		publicEndTime = _publicStartTime + 4 weeks;
    		btcsAddress = _btcs;
    		multisigAddress = _multisig;
    		matchpoolAddress = _matchpool;
    		gupToken = new GUPToken(this, publicEndTime);
    		gupToken.createIlliquidToken(matchpoolAddress, ALLOC_ILLIQUID_TEAM);
    		gupToken.createToken(matchpoolAddress, ALLOC_BOUNTIES);
    		gupToken.createToken(matchpoolAddress, ALLOC_LIQUID_TEAM);
    		gupToken.createToken(matchpoolAddress, ALLOC_NEW_USERS);
    	}
    
    	//May be used by owner of contract to halt crowdsale and no longer except ether.
    	function toggleHalt(bool _halted)
    		only_owner
    	{
    		halted = _halted;
    	}
    
    	//constant function returns the current GUP price.
    	function getPriceRate()
    		constant
    		returns (uint o_rate)
    	{
    		if (now <= publicStartTime + STAGE_ONE_TIME_END) return PRICE_STAGE_ONE;
    		if (now <= publicStartTime + STAGE_TWO_TIME_END) return PRICE_STAGE_TWO;
    		if (now <= publicStartTime + STAGE_THREE_TIME_END) return PRICE_STAGE_THREE;
    		if (now <= publicStartTime + STAGE_FOUR_TIME_END) return PRICE_STAGE_FOUR;
    		else return 0;
    	}
    
    	// Given the rate of a purchase and the remaining tokens in this tranche, it
    	// will throw if the sale would take it past the limit of the tranche.
    	// It executes the purchase for the appropriate amount of tokens, which
    	// involves adding it to the total, minting GUP tokens and stashing the
    	// ether.
    	// Returns `amount` in scope as the number of GUP tokens that it will
    	// purchase.
    	function processPurchase(uint _rate, uint _remaining)
    		internal
    		returns (uint o_amount)
    	{
    		o_amount = safeDiv(safeMul(msg.value, _rate), 1 ether);
    		if (o_amount > _remaining) throw;
    		if (!multisigAddress.send(msg.value)) throw;
    		if (!gupToken.createToken(msg.sender, o_amount)) throw;
    		gupSold += o_amount;
    		etherRaised += msg.value;
    	}
    
    	//Special Function can only be called by BTC Suisse and only during the pre-crowdsale period.
    	//Allows the purchase of up to 125000 Ether worth of GUP Tokens.
    	function preBuy()
    		payable
    		is_pre_crowdfund_period
    		only_btcs
    		is_not_halted
    	{
    		uint amount = processPurchase(PRICE_BTCS, BTCS_PORTION_MAX - btcsPortionTotal);
    		btcsPortionTotal += amount;
    		PreBuy(amount);
    	}
    
    	//Default function called by sending Ether to this address with no arguments.
    	//Results in creation of new GUP Tokens if transaction would not exceed hard limit of GUP Token.
    	function()
    		payable
    		is_crowdfund_period
    		is_not_halted
    	{
    		uint amount = processPurchase(getPriceRate(), ALLOC_CROWDSALE - gupSold);
    		Buy(msg.sender, amount);
    	}
    
    	//failsafe drain
    	function drain()
    		only_owner
    	{
    		if (!ownerAddress.send(this.balance)) throw;
    	}
    }

    File 2 of 3: Wallet
    //sol Wallet
    // Multi-sig, daily-limited account proxy/wallet.
    // @authors:
    // Gav Wood <g@ethdev.com>
    // inheritable "property" contract that enables methods to be protected by requiring the acquiescence of either a
    // single, or, crucially, each of a number of, designated owners.
    // usage:
    // use modifiers onlyowner (just own owned) or onlymanyowners(hash), whereby the same hash must be provided by
    // some number (specified in constructor) of the set of owners (specified in the constructor, modifiable) before the
    // interior is executed.
    
    pragma solidity ^0.4.9;
    
    contract WalletEvents {
      // EVENTS
    
      // this contract only has six types of events: it can accept a confirmation, in which case
      // we record owner and operation (hash) alongside it.
      event Confirmation(address owner, bytes32 operation);
      event Revoke(address owner, bytes32 operation);
    
      // some others are in the case of an owner changing.
      event OwnerChanged(address oldOwner, address newOwner);
      event OwnerAdded(address newOwner);
      event OwnerRemoved(address oldOwner);
    
      // the last one is emitted if the required signatures change
      event RequirementChanged(uint newRequirement);
    
      // Funds has arrived into the wallet (record how much).
      event Deposit(address _from, uint value);
      // Single transaction going out of the wallet (record who signed for it, how much, and to whom it's going).
      event SingleTransact(address owner, uint value, address to, bytes data, address created);
      // Multi-sig transaction going out of the wallet (record who signed for it last, the operation hash, how much, and to whom it's going).
      event MultiTransact(address owner, bytes32 operation, uint value, address to, bytes data, address created);
      // Confirmation still needed for a transaction.
      event ConfirmationNeeded(bytes32 operation, address initiator, uint value, address to, bytes data);
    }
    
    contract WalletAbi {
      // Revokes a prior confirmation of the given operation
      function revoke(bytes32 _operation) external;
    
      // Replaces an owner `_from` with another `_to`.
      function changeOwner(address _from, address _to) external;
    
      function addOwner(address _owner) external;
    
      function removeOwner(address _owner) external;
    
      function changeRequirement(uint _newRequired) external;
    
      function isOwner(address _addr) constant returns (bool);
    
      function hasConfirmed(bytes32 _operation, address _owner) external constant returns (bool);
    
      // (re)sets the daily limit. needs many of the owners to confirm. doesn't alter the amount already spent today.
      function setDailyLimit(uint _newLimit) external;
    
      function execute(address _to, uint _value, bytes _data) external returns (bytes32 o_hash);
      function confirm(bytes32 _h) returns (bool o_success);
    }
    
    contract WalletLibrary is WalletEvents {
      // TYPES
    
      // struct for the status of a pending operation.
      struct PendingState {
        uint yetNeeded;
        uint ownersDone;
        uint index;
      }
    
      // Transaction structure to remember details of transaction lest it need be saved for a later call.
      struct Transaction {
        address to;
        uint value;
        bytes data;
      }
    
      // MODIFIERS
    
      // simple single-sig function modifier.
      modifier onlyowner {
        if (isOwner(msg.sender))
          _;
      }
      // multi-sig function modifier: the operation must have an intrinsic hash in order
      // that later attempts can be realised as the same underlying operation and
      // thus count as confirmations.
      modifier onlymanyowners(bytes32 _operation) {
        if (confirmAndCheck(_operation))
          _;
      }
    
      // METHODS
    
      // gets called when no other function matches
      function() payable {
        // just being sent some cash?
        if (msg.value > 0)
          Deposit(msg.sender, msg.value);
      }
    
      // constructor is given number of sigs required to do protected "onlymanyowners" transactions
      // as well as the selection of addresses capable of confirming them.
      function initMultiowned(address[] _owners, uint _required) {
        m_numOwners = _owners.length + 1;
        m_owners[1] = uint(msg.sender);
        m_ownerIndex[uint(msg.sender)] = 1;
        for (uint i = 0; i < _owners.length; ++i)
        {
          m_owners[2 + i] = uint(_owners[i]);
          m_ownerIndex[uint(_owners[i])] = 2 + i;
        }
        m_required = _required;
      }
    
      // Revokes a prior confirmation of the given operation
      function revoke(bytes32 _operation) external {
        uint ownerIndex = m_ownerIndex[uint(msg.sender)];
        // make sure they're an owner
        if (ownerIndex == 0) return;
        uint ownerIndexBit = 2**ownerIndex;
        var pending = m_pending[_operation];
        if (pending.ownersDone & ownerIndexBit > 0) {
          pending.yetNeeded++;
          pending.ownersDone -= ownerIndexBit;
          Revoke(msg.sender, _operation);
        }
      }
    
      // Replaces an owner `_from` with another `_to`.
      function changeOwner(address _from, address _to) onlymanyowners(sha3(msg.data)) external {
        if (isOwner(_to)) return;
        uint ownerIndex = m_ownerIndex[uint(_from)];
        if (ownerIndex == 0) return;
    
        clearPending();
        m_owners[ownerIndex] = uint(_to);
        m_ownerIndex[uint(_from)] = 0;
        m_ownerIndex[uint(_to)] = ownerIndex;
        OwnerChanged(_from, _to);
      }
    
      function addOwner(address _owner) onlymanyowners(sha3(msg.data)) external {
        if (isOwner(_owner)) return;
    
        clearPending();
        if (m_numOwners >= c_maxOwners)
          reorganizeOwners();
        if (m_numOwners >= c_maxOwners)
          return;
        m_numOwners++;
        m_owners[m_numOwners] = uint(_owner);
        m_ownerIndex[uint(_owner)] = m_numOwners;
        OwnerAdded(_owner);
      }
    
      function removeOwner(address _owner) onlymanyowners(sha3(msg.data)) external {
        uint ownerIndex = m_ownerIndex[uint(_owner)];
        if (ownerIndex == 0) return;
        if (m_required > m_numOwners - 1) return;
    
        m_owners[ownerIndex] = 0;
        m_ownerIndex[uint(_owner)] = 0;
        clearPending();
        reorganizeOwners(); //make sure m_numOwner is equal to the number of owners and always points to the optimal free slot
        OwnerRemoved(_owner);
      }
    
      function changeRequirement(uint _newRequired) onlymanyowners(sha3(msg.data)) external {
        if (_newRequired > m_numOwners) return;
        m_required = _newRequired;
        clearPending();
        RequirementChanged(_newRequired);
      }
    
      // Gets an owner by 0-indexed position (using numOwners as the count)
      function getOwner(uint ownerIndex) external constant returns (address) {
        return address(m_owners[ownerIndex + 1]);
      }
    
      function isOwner(address _addr) constant returns (bool) {
        return m_ownerIndex[uint(_addr)] > 0;
      }
    
      function hasConfirmed(bytes32 _operation, address _owner) external constant returns (bool) {
        var pending = m_pending[_operation];
        uint ownerIndex = m_ownerIndex[uint(_owner)];
    
        // make sure they're an owner
        if (ownerIndex == 0) return false;
    
        // determine the bit to set for this owner.
        uint ownerIndexBit = 2**ownerIndex;
        return !(pending.ownersDone & ownerIndexBit == 0);
      }
    
      // constructor - stores initial daily limit and records the present day's index.
      function initDaylimit(uint _limit) {
        m_dailyLimit = _limit;
        m_lastDay = today();
      }
      // (re)sets the daily limit. needs many of the owners to confirm. doesn't alter the amount already spent today.
      function setDailyLimit(uint _newLimit) onlymanyowners(sha3(msg.data)) external {
        m_dailyLimit = _newLimit;
      }
      // resets the amount already spent today. needs many of the owners to confirm.
      function resetSpentToday() onlymanyowners(sha3(msg.data)) external {
        m_spentToday = 0;
      }
    
      // constructor - just pass on the owner array to the multiowned and
      // the limit to daylimit
      function initWallet(address[] _owners, uint _required, uint _daylimit) {
        initDaylimit(_daylimit);
        initMultiowned(_owners, _required);
      }
    
      // kills the contract sending everything to `_to`.
      function kill(address _to) onlymanyowners(sha3(msg.data)) external {
        suicide(_to);
      }
    
      // Outside-visible transact entry point. Executes transaction immediately if below daily spend limit.
      // If not, goes into multisig process. We provide a hash on return to allow the sender to provide
      // shortcuts for the other confirmations (allowing them to avoid replicating the _to, _value
      // and _data arguments). They still get the option of using them if they want, anyways.
      function execute(address _to, uint _value, bytes _data) external onlyowner returns (bytes32 o_hash) {
        // first, take the opportunity to check that we're under the daily limit.
        if ((_data.length == 0 && underLimit(_value)) || m_required == 1) {
          // yes - just execute the call.
          address created;
          if (_to == 0) {
            created = create(_value, _data);
          } else {
            if (!_to.call.value(_value)(_data))
              throw;
          }
          SingleTransact(msg.sender, _value, _to, _data, created);
        } else {
          // determine our operation hash.
          o_hash = sha3(msg.data, block.number);
          // store if it's new
          if (m_txs[o_hash].to == 0 && m_txs[o_hash].value == 0 && m_txs[o_hash].data.length == 0) {
            m_txs[o_hash].to = _to;
            m_txs[o_hash].value = _value;
            m_txs[o_hash].data = _data;
          }
          if (!confirm(o_hash)) {
            ConfirmationNeeded(o_hash, msg.sender, _value, _to, _data);
          }
        }
      }
    
      function create(uint _value, bytes _code) internal returns (address o_addr) {
        assembly {
          o_addr := create(_value, add(_code, 0x20), mload(_code))
          jumpi(invalidJumpLabel, iszero(extcodesize(o_addr)))
        }
      }
    
      // confirm a transaction through just the hash. we use the previous transactions map, m_txs, in order
      // to determine the body of the transaction from the hash provided.
      function confirm(bytes32 _h) onlymanyowners(_h) returns (bool o_success) {
        if (m_txs[_h].to != 0 || m_txs[_h].value != 0 || m_txs[_h].data.length != 0) {
          address created;
          if (m_txs[_h].to == 0) {
            created = create(m_txs[_h].value, m_txs[_h].data);
          } else {
            if (!m_txs[_h].to.call.value(m_txs[_h].value)(m_txs[_h].data))
              throw;
          }
    
          MultiTransact(msg.sender, _h, m_txs[_h].value, m_txs[_h].to, m_txs[_h].data, created);
          delete m_txs[_h];
          return true;
        }
      }
    
      // INTERNAL METHODS
    
      function confirmAndCheck(bytes32 _operation) internal returns (bool) {
        // determine what index the present sender is:
        uint ownerIndex = m_ownerIndex[uint(msg.sender)];
        // make sure they're an owner
        if (ownerIndex == 0) return;
    
        var pending = m_pending[_operation];
        // if we're not yet working on this operation, switch over and reset the confirmation status.
        if (pending.yetNeeded == 0) {
          // reset count of confirmations needed.
          pending.yetNeeded = m_required;
          // reset which owners have confirmed (none) - set our bitmap to 0.
          pending.ownersDone = 0;
          pending.index = m_pendingIndex.length++;
          m_pendingIndex[pending.index] = _operation;
        }
        // determine the bit to set for this owner.
        uint ownerIndexBit = 2**ownerIndex;
        // make sure we (the message sender) haven't confirmed this operation previously.
        if (pending.ownersDone & ownerIndexBit == 0) {
          Confirmation(msg.sender, _operation);
          // ok - check if count is enough to go ahead.
          if (pending.yetNeeded <= 1) {
            // enough confirmations: reset and run interior.
            delete m_pendingIndex[m_pending[_operation].index];
            delete m_pending[_operation];
            return true;
          }
          else
          {
            // not enough: record that this owner in particular confirmed.
            pending.yetNeeded--;
            pending.ownersDone |= ownerIndexBit;
          }
        }
      }
    
      function reorganizeOwners() private {
        uint free = 1;
        while (free < m_numOwners)
        {
          while (free < m_numOwners && m_owners[free] != 0) free++;
          while (m_numOwners > 1 && m_owners[m_numOwners] == 0) m_numOwners--;
          if (free < m_numOwners && m_owners[m_numOwners] != 0 && m_owners[free] == 0)
          {
            m_owners[free] = m_owners[m_numOwners];
            m_ownerIndex[m_owners[free]] = free;
            m_owners[m_numOwners] = 0;
          }
        }
      }
    
      // checks to see if there is at least `_value` left from the daily limit today. if there is, subtracts it and
      // returns true. otherwise just returns false.
      function underLimit(uint _value) internal onlyowner returns (bool) {
        // reset the spend limit if we're on a different day to last time.
        if (today() > m_lastDay) {
          m_spentToday = 0;
          m_lastDay = today();
        }
        // check to see if there's enough left - if so, subtract and return true.
        // overflow protection                    // dailyLimit check
        if (m_spentToday + _value >= m_spentToday && m_spentToday + _value <= m_dailyLimit) {
          m_spentToday += _value;
          return true;
        }
        return false;
      }
    
      // determines today's index.
      function today() private constant returns (uint) { return now / 1 days; }
    
      function clearPending() internal {
        uint length = m_pendingIndex.length;
    
        for (uint i = 0; i < length; ++i) {
          delete m_txs[m_pendingIndex[i]];
    
          if (m_pendingIndex[i] != 0)
            delete m_pending[m_pendingIndex[i]];
        }
    
        delete m_pendingIndex;
      }
    
      // FIELDS
      address constant _walletLibrary = 0xa657491c1e7f16adb39b9b60e87bbb8d93988bc3;
    
      // the number of owners that must confirm the same operation before it is run.
      uint public m_required;
      // pointer used to find a free slot in m_owners
      uint public m_numOwners;
    
      uint public m_dailyLimit;
      uint public m_spentToday;
      uint public m_lastDay;
    
      // list of owners
      uint[256] m_owners;
    
      uint constant c_maxOwners = 250;
      // index on the list of owners to allow reverse lookup
      mapping(uint => uint) m_ownerIndex;
      // the ongoing operations.
      mapping(bytes32 => PendingState) m_pending;
      bytes32[] m_pendingIndex;
    
      // pending transactions we have at present.
      mapping (bytes32 => Transaction) m_txs;
    }
    
    contract Wallet is WalletEvents {
    
      // WALLET CONSTRUCTOR
      //   calls the `initWallet` method of the Library in this context
      function Wallet(address[] _owners, uint _required, uint _daylimit) {
        // Signature of the Wallet Library's init function
        bytes4 sig = bytes4(sha3("initWallet(address[],uint256,uint256)"));
        address target = _walletLibrary;
    
        // Compute the size of the call data : arrays has 2
        // 32bytes for offset and length, plus 32bytes per element ;
        // plus 2 32bytes for each uint
        uint argarraysize = (2 + _owners.length);
        uint argsize = (2 + argarraysize) * 32;
    
        assembly {
          // Add the signature first to memory
          mstore(0x0, sig)
          // Add the call data, which is at the end of the
          // code
          codecopy(0x4,  sub(codesize, argsize), argsize)
          // Delegate call to the library
          delegatecall(sub(gas, 10000), target, 0x0, add(argsize, 0x4), 0x0, 0x0)
        }
      }
    
      // METHODS
    
      // gets called when no other function matches
      function() payable {
        // just being sent some cash?
        if (msg.value > 0)
          Deposit(msg.sender, msg.value);
        else if (msg.data.length > 0)
          _walletLibrary.delegatecall(msg.data);
      }
    
      // Gets an owner by 0-indexed position (using numOwners as the count)
      function getOwner(uint ownerIndex) constant returns (address) {
        return address(m_owners[ownerIndex + 1]);
      }
    
      // As return statement unavailable in fallback, explicit the method here
    
      function hasConfirmed(bytes32 _operation, address _owner) external constant returns (bool) {
        return _walletLibrary.delegatecall(msg.data);
      }
    
      function isOwner(address _addr) constant returns (bool) {
        return _walletLibrary.delegatecall(msg.data);
      }
    
      // FIELDS
      address constant _walletLibrary = 0xa657491c1e7f16adb39b9b60e87bbb8d93988bc3;
    
      // the number of owners that must confirm the same operation before it is run.
      uint public m_required;
      // pointer used to find a free slot in m_owners
      uint public m_numOwners;
    
      uint public m_dailyLimit;
      uint public m_spentToday;
      uint public m_lastDay;
    
      // list of owners
      uint[256] m_owners;
    }

    File 3 of 3: GUPToken
    pragma solidity ^0.4.8;
    
    
    contract SafeMath {
    
      function assert(bool assertion) internal {
        if (!assertion) throw;
      }
    
      function safeMul(uint a, uint b) internal returns (uint) {
        uint c = a * b;
        assert(a == 0 || c / a == b);
        return c;
      }
    
      function safeDiv(uint a, uint b) internal returns (uint) {
        assert(b > 0);
        uint c = a / b;
        assert(a == b * c + a % b);
        return c;
      }
    
    }
    
    
    contract StandardTokenProtocol {
    
        function totalSupply() constant returns (uint256 totalSupply) {}
        function balanceOf(address _owner) constant returns (uint256 balance) {}
        function transfer(address _recipient, uint256 _value) returns (bool success) {}
        function transferFrom(address _from, address _recipient, uint256 _value) returns (bool success) {}
        function approve(address _spender, uint256 _value) returns (bool success) {}
        function allowance(address _owner, address _spender) constant returns (uint256 remaining) {}
    
        event Transfer(address indexed _from, address indexed _recipient, uint256 _value);
        event Approval(address indexed _owner, address indexed _spender, uint256 _value);
    
    }
    
    
    contract StandardToken is StandardTokenProtocol {
    
        modifier when_can_transfer(address _from, uint256 _value) {
            if (balances[_from] >= _value) _;
        }
    
        modifier when_can_receive(address _recipient, uint256 _value) {
            if (balances[_recipient] + _value > balances[_recipient]) _;
        }
    
        modifier when_is_allowed(address _from, address _delegate, uint256 _value) {
            if (allowed[_from][_delegate] >= _value) _;
        }
    
        function transfer(address _recipient, uint256 _value)
            when_can_transfer(msg.sender, _value)
            when_can_receive(_recipient, _value)
            returns (bool o_success)
        {
            balances[msg.sender] -= _value;
            balances[_recipient] += _value;
            Transfer(msg.sender, _recipient, _value);
            return true;
        }
    
        function transferFrom(address _from, address _recipient, uint256 _value)
            when_can_transfer(_from, _value)
            when_can_receive(_recipient, _value)
            when_is_allowed(_from, msg.sender, _value)
            returns (bool o_success)
        {
            allowed[_from][msg.sender] -= _value;
            balances[_from] -= _value;
            balances[_recipient] += _value;
            Transfer(_from, _recipient, _value);
            return true;
        }
    
        function balanceOf(address _owner) constant returns (uint256 balance) {
            return balances[_owner];
        }
    
        function approve(address _spender, uint256 _value) returns (bool o_success) {
            allowed[msg.sender][_spender] = _value;
            Approval(msg.sender, _spender, _value);
            return true;
        }
    
        function allowance(address _owner, address _spender) constant returns (uint256 o_remaining) {
            return allowed[_owner][_spender];
        }
    
        mapping (address => uint256) balances;
        mapping (address => mapping (address => uint256)) allowed;
        uint256 public totalSupply;
    
    }
    
    contract GUPToken is StandardToken {
    
    	//FIELDS
    	string public name = "Guppy";
        string public symbol = "GUP";
        uint public decimals = 3;
    
    	//CONSTANTS
    	uint public constant LOCKOUT_PERIOD = 1 years; //time after end date that illiquid GUP can be transferred
    
    	//ASSIGNED IN INITIALIZATION
    	uint public endMintingTime; //Timestamp after which no more tokens can be created
    	address public minter; //address of the account which may mint new tokens
    
    	mapping (address => uint) public illiquidBalance; //Balance of 'Frozen funds'
    
    	//MODIFIERS
    	//Can only be called by contribution contract.
    	modifier only_minter {
    		if (msg.sender != minter) throw;
    		_;
    	}
    
    	// Can only be called if illiquid tokens may be transformed into liquid.
    	// This happens when `LOCKOUT_PERIOD` of time passes after `endMintingTime`.
    	modifier when_thawable {
    		if (now < endMintingTime + LOCKOUT_PERIOD) throw;
    		_;
    	}
    
    	// Can only be called if (liquid) tokens may be transferred. Happens
    	// immediately after `endMintingTime`.
    	modifier when_transferable {
    		if (now < endMintingTime) throw;
    		_;
    	}
    
    	// Can only be called if the `crowdfunder` is allowed to mint tokens. Any
    	// time before `endMintingTime`.
    	modifier when_mintable {
    		if (now >= endMintingTime) throw;
    		_;
    	}
    
    	// Initialization contract assigns address of crowdfund contract and end time.
    	function GUPToken(address _minter, uint _endMintingTime) {
    		endMintingTime = _endMintingTime;
    		minter = _minter;
    	}
    
    	// Create new tokens when called by the crowdfund contract.
    	// Only callable before the end time.
    	function createToken(address _recipient, uint _value)
    		when_mintable
    		only_minter
    		returns (bool o_success)
    	{
    		balances[_recipient] += _value;
    		totalSupply += _value;
    		return true;
    	}
    
    	// Create an illiquidBalance which cannot be traded until end of lockout period.
    	// Can only be called by crowdfund contract before the end time.
    	function createIlliquidToken(address _recipient, uint _value)
    		when_mintable
    		only_minter
    		returns (bool o_success)
    	{
    		illiquidBalance[_recipient] += _value;
    		totalSupply += _value;
    		return true;
    	}
    
    	// Make sender's illiquid balance liquid when called after lockout period.
    	function makeLiquid()
    		when_thawable
    	{
    		balances[msg.sender] += illiquidBalance[msg.sender];
    		illiquidBalance[msg.sender] = 0;
    	}
    
    	// Transfer amount of tokens from sender account to recipient.
    	// Only callable after the crowd fund end date.
    	function transfer(address _recipient, uint _amount)
    		when_transferable
    		returns (bool o_success)
    	{
    		return super.transfer(_recipient, _amount);
    	}
    
    	// Transfer amount of tokens from a specified address to a recipient.
    	// Only callable after the crowd fund end date.
    	function transferFrom(address _from, address _recipient, uint _amount)
    		when_transferable
    		returns (bool o_success)
    	{
    		return super.transferFrom(_from, _recipient, _amount);
    	}
    }