Contract 0x0aba2066c9e03be70e431352d4e82dac9b3082d9

Contract Overview

Balance:
0 Ether

Latest 1 internal transaction Internal Transactions as a result of Contract Execution

Parent TxHash Block Age From To Value
0x2ee6434688789977088be74ac9d31598915c6922b573ef151858a2a455de3d502891883202 days 18 hrs ago0x953faab4dfc6c5aa2b024b5be2a384e3e63dfaf40x0aba2066c9e03be70e431352d4e82dac9b3082d90 Ether
[ Download CSV Export 
Warning: The compiled contract might be susceptible to ExpExponentCleanup (medium/high-severity), EventStructWrongData (very low-severity) Solidity Compiler Bugs.

Contract Source Code Verified (Similar Match)
Note: This contract matches the deployed ByteCode of the Verified Source Code for Contract 0xb15805ae3572739cbac6bf5fffc5758f257b22b5
Contract Name: EthDistributor
Compiler Version: v0.4.23+commit.124ca40d
Optimization Enabled: Yes
Runs (Optimizer):  200


Contract Source Code
pragma solidity 0.4.23;

// File: contracts/IFinalizable.sol

/*
    Managed contract interface
*/
contract IFinalizable {
    // this function isn't abstract since the compiler emits automatically generated getter functions as external
    function isFinalized() public view returns (bool) {}
    function finalize() public;
}

// File: bancor-contracts/solidity/contracts/interfaces/IOwned.sol

/*
    Owned contract interface
*/
contract IOwned {
    // this function isn't abstract since the compiler emits automatically generated getter functions as external
    function owner() public view returns (address) {}

    function transferOwnership(address _newOwner) public;
    function acceptOwnership() public;
}

// File: bancor-contracts/solidity/contracts/Owned.sol

/*
    Provides support and utilities for contract ownership
*/
contract Owned is IOwned {
    address public owner;
    address public newOwner;

    event OwnerUpdate(address indexed _prevOwner, address indexed _newOwner);

    /**
        @dev constructor
    */
    function Owned() public {
        owner = msg.sender;
    }

    // allows execution by the owner only
    modifier ownerOnly {
        assert(msg.sender == owner);
        _;
    }

    /**
        @dev allows transferring the contract ownership
        the new owner still needs to accept the transfer
        can only be called by the contract owner

        @param _newOwner    new contract owner
    */
    function transferOwnership(address _newOwner) public ownerOnly {
        require(_newOwner != owner);
        newOwner = _newOwner;
    }

    /**
        @dev used by a new owner to accept an ownership transfer
    */
    function acceptOwnership() public {
        require(msg.sender == newOwner);
        OwnerUpdate(owner, newOwner);
        owner = newOwner;
        newOwner = address(0);
    }
}

// File: bancor-contracts/solidity/contracts/Utils.sol

/*
    Utilities & Common Modifiers
*/
contract Utils {
    /**
        constructor
    */
    function Utils() public {
    }

    // verifies that an amount is greater than zero
    modifier greaterThanZero(uint256 _amount) {
        require(_amount > 0);
        _;
    }

    // validates an address - currently only checks that it isn't null
    modifier validAddress(address _address) {
        require(_address != address(0));
        _;
    }

    // verifies that the address is different than this contract address
    modifier notThis(address _address) {
        require(_address != address(this));
        _;
    }

    // Overflow protected math functions

    /**
        @dev returns the sum of _x and _y, asserts if the calculation overflows

        @param _x   value 1
        @param _y   value 2

        @return sum
    */
    function safeAdd(uint256 _x, uint256 _y) internal pure returns (uint256) {
        uint256 z = _x + _y;
        assert(z >= _x);
        return z;
    }

    /**
        @dev returns the difference of _x minus _y, asserts if the subtraction results in a negative number

        @param _x   minuend
        @param _y   subtrahend

        @return difference
    */
    function safeSub(uint256 _x, uint256 _y) internal pure returns (uint256) {
        assert(_x >= _y);
        return _x - _y;
    }

    /**
        @dev returns the product of multiplying _x by _y, asserts if the calculation overflows

        @param _x   factor 1
        @param _y   factor 2

        @return product
    */
    function safeMul(uint256 _x, uint256 _y) internal pure returns (uint256) {
        uint256 z = _x * _y;
        assert(_x == 0 || z / _x == _y);
        return z;
    }
}

// File: bancor-contracts/solidity/contracts/interfaces/IERC20Token.sol

/*
    ERC20 Standard Token interface
*/
contract IERC20Token {
    // these functions aren't abstract since the compiler emits automatically generated getter functions as external
    function name() public view returns (string) {}
    function symbol() public view returns (string) {}
    function decimals() public view returns (uint8) {}
    function totalSupply() public view returns (uint256) {}
    function balanceOf(address _owner) public view returns (uint256) { _owner; }
    function allowance(address _owner, address _spender) public view returns (uint256) { _owner; _spender; }

    function transfer(address _to, uint256 _value) public returns (bool success);
    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
    function approve(address _spender, uint256 _value) public returns (bool success);
}

// File: bancor-contracts/solidity/contracts/interfaces/ITokenHolder.sol

/*
    Token Holder interface
*/
contract ITokenHolder is IOwned {
    function withdrawTokens(IERC20Token _token, address _to, uint256 _amount) public;
}

// File: bancor-contracts/solidity/contracts/TokenHolder.sol

/*
    We consider every contract to be a 'token holder' since it's currently not possible
    for a contract to deny receiving tokens.

    The TokenHolder's contract sole purpose is to provide a safety mechanism that allows
    the owner to send tokens that were sent to the contract by mistake back to their sender.
*/
contract TokenHolder is ITokenHolder, Owned, Utils {
    /**
        @dev constructor
    */
    function TokenHolder() public {
    }

    /**
        @dev withdraws tokens held by the contract and sends them to an account
        can only be called by the owner

        @param _token   ERC20 token contract address
        @param _to      account to receive the new amount
        @param _amount  amount to withdraw
    */
    function withdrawTokens(IERC20Token _token, address _to, uint256 _amount)
        public
        ownerOnly
        validAddress(_token)
        validAddress(_to)
        notThis(_to)
    {
        assert(_token.transfer(_to, _amount));
    }
}

// File: bancor-contracts/solidity/contracts/interfaces/IEtherToken.sol

/*
    Ether Token interface
*/
contract IEtherToken is ITokenHolder, IERC20Token {
    function deposit() public payable;
    function withdraw(uint256 _amount) public;
    function withdrawTo(address _to, uint256 _amount) public;
}

// File: contracts/EthDistributor.sol

// distributes received ether in following fashion
// 1) if (totalReceived() < beneficiary1_Threshold) beneficiary0 gets everything (NOTE: actually he gets it after finalization because before finalization we need to keep potential allocation for beneficiary1)
//    else beneficiary0 gets up to min(beneficiary1_Threshold, (1 - (beneficiary1_Numerator/beneficiary1_Denominator)) * totalReceived())
// 2) after beneficiary0 is satisfied beneficiary1 gets up to (beneficiary1_Numerator/beneficiary1_Denominator) * totalReceived()
// 3) after beneficiary1 is satisfied beneficiary2 gets the rest of balance
// ether can be distributed repeatedly at any point without any limitation
// NOTE: the owner will actually be DriveCrowdsale so we don't have controll over it

/* USAGE
 * Withdraw (repeatedly):
 * 1) ethDistributor.distribute()
 * 2) ethDistributor.withdraw(0)
 * 3) ethDistributor.withdraw(1)
 * 4) ethDistributor.withdraw(2)
 * 5) ethDistributor.transferEtherToken()
 */
contract EthDistributor is TokenHolder, IFinalizable
{
    struct Beneficiary
    {
        address addr;
        uint withdrawn;
        uint pending;
    }

    Beneficiary[3] public beneficiaries;

    uint public beneficiary1_Threshold;
    uint public beneficiary1_Numerator;
    uint public beneficiary1_Denominator;
    address public beneficiary1_Recipient;

    bool public isFinalized;

    constructor(address _beneficiary0, IEtherToken _beneficiary1_EtherToken, address _beneficiary1_Recipient, uint _beneficiary1_Threshold, uint _beneficiary1_Numerator, uint _beneficiary1_Denominator, address _beneficiary2)
        validAddress(_beneficiary0)
        validAddress(_beneficiary1_EtherToken)
        validAddress(_beneficiary1_Recipient)
        validAddress(_beneficiary2)
        public
    {
        require(_beneficiary1_Numerator <= _beneficiary1_Denominator);
        require(0 < _beneficiary1_Denominator);

        beneficiaries[0].addr = _beneficiary0;
        beneficiaries[1].addr = _beneficiary1_EtherToken;
        beneficiary1_Recipient = _beneficiary1_Recipient;
        beneficiary1_Threshold = _beneficiary1_Threshold;
        beneficiary1_Numerator = _beneficiary1_Numerator;
        beneficiary1_Denominator = _beneficiary1_Denominator;
        beneficiaries[2].addr = _beneficiary2;
    }

    // pattern of splitting withdrawals into two methods
    // distribute() sets pending amounts for all beneficiaries
    function distribute() public // NOTE: since beneficiaries are predefined we don't do any access management
    {
        uint pendingTotal;
        for(uint8 i = 0; i < beneficiaries.length; i++)
        {
            if(pendingTotal < address(this).balance)
                beneficiaries[i].pending = 
                    min(
                        safeSub(maxAllocation(i), beneficiaries[i].withdrawn), 
                        safeSub(address(this).balance, pendingTotal));
            else
                beneficiaries[i].pending = 0;
            pendingTotal += beneficiaries[i].pending;
        }
    }

    // pattern of splitting withdrawals into two methods
    // withdraw() withdraws pending amount for one particular beneficiary
    function withdraw(uint8 _index) public // NOTE: since beneficiaries are predefined we don't do any access management
    {   
        uint256 amount = upToBalance(beneficiaries[_index].pending);
        require(0 < amount);
        beneficiaries[_index].pending -= amount;
        beneficiaries[_index].withdrawn += amount;
        // must be at the end to avoid reentrancy
        // pass gass
        // NOTE: call() doesn't propagate errors so it is essential to check return value
        require(beneficiaries[_index].addr.call.value(amount)());
    }

    function transferEtherToken() public // NOTE: since beneficiaries are predefined we don't do any access management
    {
        IEtherToken(beneficiaries[1].addr).transfer(beneficiary1_Recipient, IEtherToken(beneficiaries[1].addr).balanceOf(this));
    }

    // Finalization does just one thing and that is that it releases the percentage hold for beneficiary1 if the beneficiary1_Threshold isn’t reached
    function finalize() ownerOnly public
    {
        require(!isFinalized);
        isFinalized = true;
    }

    function beneficiariesCount() public view returns (uint8)
    {
        return uint8(beneficiaries.length);
    }

    // how much is at most allocated for given beneficiary (including already withdrawn amount)
    // note: given beneficiary actually isn't guaranteed that he gets the full amount (in case previous beneficiary with lower index already got the balance)
    function maxAllocation(uint8 _index) internal view returns(uint)
    {
        // returns allocation for beneficiary0
        if(_index == 0)
            // if we are finalized and we didn't reach beneficiary1_Threshold
            // beneficiary0 gets everything
            if(isFinalized && totalReceived() < beneficiary1_Threshold)
                return totalReceived();
            else
            { // beneficiary0 gets up to beneficiary1_Threshold minus
              // what is needed for beneficiary1
                
                // baseAllocation for beneficiary0 + beneficiary1
                uint baseAllocation = beneficiary1_Threshold;
                if(beneficiary1_Threshold < totalReceived())
                    baseAllocation = totalReceived();

                uint beneficiary0Share = safeSub(baseAllocation, beneficiary1Share(baseAllocation));
                return min(beneficiary1_Threshold, beneficiary0Share);
            }
        // returns allocation for beneficiary1
        else if(_index == 1)
            if(totalReceived() < beneficiary1_Threshold)
                return 0;
            else
                return beneficiary1Share(totalReceived());
        // returns allocation for beneficiary2
        else if(_index == 2)
            if(totalReceived() < beneficiary1_Threshold)
                return 0;
            else
                // beneficiary2 gets everything what's left. method distribute() is actually responsible for calculating the amount for beneficiary2
                return totalReceived();
        else
            revert();
    }

    function withdrawnTotal() public view returns(uint)
    {
        uint result;
        for(uint8 i = 0; i < beneficiaries.length; i++)
            result = safeAdd(result, beneficiaries[i].withdrawn);
        return result;
    }

    function totalReceived() public view returns (uint)
    {
        return safeAdd(address(this).balance, withdrawnTotal());
    }

    function upToBalance(uint _amount) internal view returns(uint)
    {
        return min(address(this).balance, _amount);
    }

    function min(uint _a, uint _b) internal pure returns(uint)
    {
        if(_a < _b)
            return _a;
        return _b;
    }

    function beneficiary1Share(uint _totalReceived) internal view returns(uint)
    {
        return safeMul(beneficiary1_Numerator, _totalReceived) / beneficiary1_Denominator;
    }

    function() payable public
    {
        // nothing so it can receive by transfer() method
    }
}

Contract ABI
[{"constant":false,"inputs":[],"name":"transferEtherToken","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"finalize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"},{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"withdrawTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"withdrawnTotal","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"beneficiariesCount","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"beneficiary1_Denominator","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isFinalized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalReceived","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_index","type":"uint8"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"newOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"beneficiary1_Threshold","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"distribute","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"beneficiary1_Numerator","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"beneficiaries","outputs":[{"name":"addr","type":"address"},{"name":"withdrawn","type":"uint256"},{"name":"pending","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"beneficiary1_Recipient","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_beneficiary0","type":"address"},{"name":"_beneficiary1_EtherToken","type":"address"},{"name":"_beneficiary1_Recipient","type":"address"},{"name":"_beneficiary1_Threshold","type":"uint256"},{"name":"_beneficiary1_Numerator","type":"uint256"},{"name":"_beneficiary1_Denominator","type":"uint256"},{"name":"_beneficiary2","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_prevOwner","type":"address"},{"indexed":true,"name":"_newOwner","type":"address"}],"name":"OwnerUpdate","type":"event"}]

Contract Creation Code
608060405234801561001057600080fd5b5060405160e080610c1f83398101604090815281516020830151918301516060840151608085015160a086015160c09096015160008054600160a060020a03191633600160a060020a0390811691909117909155949693949293919287908116151561007b57600080fd5b86600160a060020a038116151561009157600080fd5b86600160a060020a03811615156100a757600080fd5b83600160a060020a03811615156100bd57600080fd5b858711156100ca57600080fd5b600086116100d757600080fd5b505060028054600160a060020a0319908116600160a060020a039b8c1617909155600580548216998b16999099179098555050600e8054871695881695909517909455600b92909255600c55600d5560088054919093169116179055610add806101426000396000f3006080604052600436106100e25763ffffffff60e060020a60003504166341c3e21e81146100e45780634bb278f3146100f95780635e35359e1461010e578063684d810b146101385780636e616a4c1461015f57806379ba50971461018a5780638165ea311461019f5780638d4e4083146101b45780638da5cb5b146101dd578063a3c2c4621461020e578063c6ab5d9014610223578063d4ee1d901461023e578063e24dabb014610253578063e4fc6b6d14610268578063ecc52a2c1461027d578063efeb5e5814610292578063f2fde38b146102d2578063fe5e00df146102f3575b005b3480156100f057600080fd5b506100e2610308565b34801561010557600080fd5b506100e2610426565b34801561011a57600080fd5b506100e2600160a060020a036004358116906024351660443561049d565b34801561014457600080fd5b5061014d6105a2565b60408051918252519081900360200190f35b34801561016b57600080fd5b506101746105e4565b6040805160ff9092168252519081900360200190f35b34801561019657600080fd5b506100e26105e9565b3480156101ab57600080fd5b5061014d610675565b3480156101c057600080fd5b506101c961067b565b604080519115158252519081900360200190f35b3480156101e957600080fd5b506101f261069c565b60408051600160a060020a039092168252519081900360200190f35b34801561021a57600080fd5b5061014d6106ab565b34801561022f57600080fd5b506100e260ff600435166106cd565b34801561024a57600080fd5b506101f261078a565b34801561025f57600080fd5b5061014d610799565b34801561027457600080fd5b506100e261079f565b34801561028957600080fd5b5061014d61086d565b34801561029e57600080fd5b506102aa600435610873565b60408051600160a060020a039094168452602084019290925282820152519081900360600190f35b3480156102de57600080fd5b506100e2600160a060020a03600435166108a1565b3480156102ff57600080fd5b506101f2610903565b600554600e54604080517f70a08231000000000000000000000000000000000000000000000000000000008152600160a060020a03308116600483015291519382169363a9059cbb93929092169184916370a082319160248083019260209291908290030181600087803b15801561037f57600080fd5b505af1158015610393573d6000803e3d6000fd5b505050506040513d60208110156103a957600080fd5b50516040805160e060020a63ffffffff8616028152600160a060020a03909316600484015260248301919091525160448083019260209291908290030181600087803b1580156103f857600080fd5b505af115801561040c573d6000803e3d6000fd5b505050506040513d602081101561042257600080fd5b5050565b60005433600160a060020a0390811691161461043e57fe5b600e5474010000000000000000000000000000000000000000900460ff161561046657600080fd5b600e805474ff0000000000000000000000000000000000000000191674010000000000000000000000000000000000000000179055565b60005433600160a060020a039081169116146104b557fe5b82600160a060020a03811615156104cb57600080fd5b82600160a060020a03811615156104e157600080fd5b8330600160a060020a031681600160a060020a03161415151561050357600080fd5b85600160a060020a031663a9059cbb86866040518363ffffffff1660e060020a0281526004018083600160a060020a0316600160a060020a0316815260200182815260200192505050602060405180830381600087803b15801561056657600080fd5b505af115801561057a573d6000803e3d6000fd5b505050506040513d602081101561059057600080fd5b5051151561059a57fe5b505050505050565b600080805b60038160ff1610156105de576105d482600260ff8416600381106105c757fe5b6003020160010154610912565b91506001016105a7565b50919050565b600390565b60015433600160a060020a0390811691161461060457600080fd5b60015460008054604051600160a060020a0393841693909116917f343765429aea5a34b3ff6a3785a98a5abb2597aca87bfbb58632c173d585373a91a3600180546000805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a03841617909155169055565b600d5481565b600e5474010000000000000000000000000000000000000000900460ff1681565b600054600160a060020a031681565b60006106c830600160a060020a0316316106c36105a2565b610912565b905090565b60006106ef600260ff8416600381106106e257fe5b6003020160020154610928565b9050600081116106fe57600080fd5b80600260ff84166003811061070f57fe5b60030201600201600082825403925050819055508060028360ff1660038110151561073657fe5b600302016001016000828254019250508190555060028260ff1660038110151561075c57fe5b6003020154604051600160a060020a03909116908290600081818185875af192505050151561042257600080fd5b600154600160a060020a031681565b600b5481565b6000805b60038160ff1610156104225730600160a060020a031631821015610826576108066107ed6107d083610944565b600260ff8516600381106107e057fe5b6003020160010154610a49565b61080130600160a060020a03163185610a49565b610a5b565b600260ff83166003811061081657fe5b6003020160020181905550610844565b6000600260ff83166003811061083857fe5b60030201600201819055505b600260ff82166003811061085457fe5b60030201600201548201915080806001019150506107a3565b600c5481565b6002816003811061088057fe5b6003020180546001820154600290920154600160a060020a03909116925083565b60005433600160a060020a039081169116146108b957fe5b600054600160a060020a03828116911614156108d457600080fd5b6001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b600e54600160a060020a031681565b60008282018381101561092157fe5b9392505050565b600061093e30600160a060020a03163183610a5b565b92915050565b6000808060ff841615156109d957600e5474010000000000000000000000000000000000000000900460ff1680156109845750600b546109826106ab565b105b15610998576109916106ab565b9250610a42565b600b5491506109a56106ab565b600b5410156109b9576109b66106ab565b91505b6109cb826109c684610a6c565b610a49565b9050610991600b5482610a5b565b8360ff1660011415610a0f57600b546109f06106ab565b10156109ff5760009250610a42565b610991610a0a6106ab565b610a6c565b8360ff1660021415610a3d57600b54610a266106ab565b1015610a355760009250610a42565b6109916106ab565b600080fd5b5050919050565b600081831015610a5557fe5b50900390565b6000818310156105de57508161093e565b6000600d54610a7d600c5484610a8d565b811515610a8657fe5b0492915050565b6000828202831580610aa95750828482811515610aa657fe5b04145b151561092157fe00a165627a7a7230582069da84a46ad89c84b904c3792a2706f5ea59a3b492f772a63d133f26fcb9e1de00290000000000000000000000000465dcce2b2d843dae5585a4336123dcd04696a3000000000000000000000000421cdb320239e9e7dd4686400ecc96cbacd96ae80000000000000000000000007ccaf7b2f338c68a134523212e5cc73678bf95ba00000000000000000000000000000000000000000000000053444835ec580000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000640000000000000000000000004136144f29073df4574bfcfb8084d23bc8767083


   Swarm Source:
bzzr://69da84a46ad89c84b904c3792a2706f5ea59a3b492f772a63d133f26fcb9e1de
Block Age Transaction Difficulty GasUsed Reward
Block Age Uncle Number Difficulty GasUsed Reward