Address Details
contract

0x1451930a28155518e1DaD0Bb4170e167ab0A3dA2

Contract Name
Distributor
Creator
0xad5e83–557abf at 0xfa5013–c5b947
Balance
0 CELO ( )
Locked CELO Balance
0.00 CELO
Voting CELO Balance
0.00 CELO
Pending Unlocked Gold
0.00 CELO
Tokens
Fetching tokens...
Transactions
151 Transactions
Transfers
0 Transfers
Gas Used
5,083,697
Last Balance Update
24085740
This contract has been verified via Sourcify. View contract in Sourcify repository
Contract name:
Distributor




Optimization enabled
true
Compiler version
v0.7.5+commit.eb77ed08




Optimization runs
200
EVM Version
istanbul




Verified at
2022-01-01T15:13:38.831874Z

StakingDistributor.sol

// SPDX-License-Identifier: AGPL-3.0-or-later

pragma solidity 0.7.5;

library SafeERC20 {
    using SafeMath for uint256;
    using Address for address;

    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    function safeApprove(IERC20 token, address spender, uint256 value) internal {

        require((value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).add(value);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender)
            .sub(value, "SafeERC20: decreased allowance below zero");
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function _callOptionalReturn(IERC20 token, bytes memory data) private {

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) { // Return data is optional
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

library SafeMath {

    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    function add32(uint32 a, uint32 b) internal pure returns (uint32) {
        uint32 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    function mul(uint256 a, uint256 b) internal pure returns (uint256) {

        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }

    // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)
    function sqrrt(uint256 a) internal pure returns (uint c) {
        if (a > 3) {
            c = a;
            uint b = add( div( a, 2), 1 );
            while (b < c) {
                c = b;
                b = div( add( div( a, b ), b), 2 );
            }
        } else if (a != 0) {
            c = 1;
        }
    }

    function percentageAmount( uint256 total_, uint8 percentage_ ) internal pure returns ( uint256 percentAmount_ ) {
        return div( mul( total_, percentage_ ), 1000 );
    }

    function substractPercentage( uint256 total_, uint8 percentageToSub_ ) internal pure returns ( uint256 result_ ) {
        return sub( total_, div( mul( total_, percentageToSub_ ), 1000 ) );
    }

    function percentageOfTotal( uint256 part_, uint256 total_ ) internal pure returns ( uint256 percent_ ) {
        return div( mul(part_, 100) , total_ );
    }

    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow, so we distribute
        return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
    }

    function quadraticPricing( uint256 payment_, uint256 multiplier_ ) internal pure returns (uint256) {
        return sqrrt( mul( multiplier_, payment_ ) );
    }

  function bondingCurve( uint256 supply_, uint256 multiplier_ ) internal pure returns (uint256) {
      return mul( multiplier_, supply_ );
  }
}

interface IERC20 {

    function totalSupply() external view returns (uint256);

    function balanceOf(address account) external view returns (uint256);

    function transfer(address recipient, uint256 amount) external returns (bool);

    function allowance(address owner, address spender) external view returns (uint256);

    function approve(address spender, uint256 amount) external returns (bool);

    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint256 value);

    event Approval(address indexed owner, address indexed spender, uint256 value);
}

library Address {

    function isContract(address account) internal view returns (bool) {
        // This method relies in extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }

    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
      return functionCall(target, data, "Address: low-level call failed");
    }

    function functionCall(
        address target, 
        bytes memory data, 
        string memory errorMessage
    ) internal returns (bytes memory) {
        return _functionCallWithValue(target, data, 0, errorMessage);
    }

    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    function functionCallWithValue(
        address target, 
        bytes memory data, 
        uint256 value, 
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: value }(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _functionCallWithValue(
        address target, 
        bytes memory data, 
        uint256 weiValue, 
        string memory errorMessage
    ) private returns (bytes memory) {
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }

    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    function functionStaticCall(
        address target, 
        bytes memory data, 
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    function functionDelegateCall(
        address target, 
        bytes memory data, 
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(
        bool success, 
        bytes memory returndata, 
        string memory errorMessage
    ) private pure returns(bytes memory) {
        if (success) {
            return returndata;
        } else {
            if (returndata.length > 0) {
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }

    function addressToString(address _address) internal pure returns(string memory) {
        bytes32 _bytes = bytes32(uint256(_address));
        bytes memory HEX = "0123456789abcdef";
        bytes memory _addr = new bytes(42);

        _addr[0] = '0';
        _addr[1] = 'x';

        for(uint256 i = 0; i < 20; i++) {
            _addr[2+i*2] = HEX[uint8(_bytes[i + 12] >> 4)];
            _addr[3+i*2] = HEX[uint8(_bytes[i + 12] & 0x0f)];
        }

        return string(_addr);

    }
}


interface IPolicy {

    function policy() external view returns (address);

    function renouncePolicy() external;
  
    function pushPolicy( address newPolicy_ ) external;

    function pullPolicy() external;
}

contract Policy is IPolicy {
    
    address internal _policy;
    address internal _newPolicy;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    constructor () {
        _policy = msg.sender;
        emit OwnershipTransferred( address(0), _policy );
    }

    function policy() public view override returns (address) {
        return _policy;
    }

    modifier onlyPolicy() {
        require( _policy == msg.sender, "Ownable: caller is not the owner" );
        _;
    }

    function renouncePolicy() public virtual override onlyPolicy() {
        emit OwnershipTransferred( _policy, address(0) );
        _policy = address(0);
    }

    function pushPolicy( address newPolicy_ ) public virtual override onlyPolicy() {
        require( newPolicy_ != address(0), "Ownable: new owner is the zero address");
        _newPolicy = newPolicy_;
    }

    function pullPolicy() public virtual override {
        require( msg.sender == _newPolicy );
        emit OwnershipTransferred( _policy, _newPolicy );
        _policy = _newPolicy;
    }
}

interface ITreasury {
    function mintRewards( address _recipient, uint _amount ) external;
}

contract Distributor is Policy {
    using SafeMath for uint;
    using SafeMath for uint32;
    using SafeERC20 for IERC20;
    
    
    
    /* ====== VARIABLES ====== */

    address public immutable OHM;
    address public immutable treasury;
    
    uint32 public immutable epochLength;
    uint32 public nextEpochTime;
    
    mapping( uint => Adjust ) public adjustments;
    
    
    /* ====== STRUCTS ====== */
        
    struct Info {
        uint rate; // in ten-thousandths ( 5000 = 0.5% )
        address recipient;
    }
    Info[] public info;
    
    struct Adjust {
        bool add;
        uint rate;
        uint target;
    }
    
    
    
    /* ====== CONSTRUCTOR ====== */

    constructor( address _treasury, address _ohm, uint32 _epochLength, uint32 _nextEpochTime ) {        
        require( _treasury != address(0) );
        treasury = _treasury;
        require( _ohm != address(0) );
        OHM = _ohm;
        epochLength = _epochLength;
        nextEpochTime = _nextEpochTime;
    }
    
    
    
    /* ====== PUBLIC FUNCTIONS ====== */
    
    /**
        @notice send epoch reward to staking contract
     */
    function distribute() external returns ( bool ) {
        if ( nextEpochTime <= uint32(block.timestamp) ) {
            nextEpochTime = nextEpochTime.add32( epochLength ); // set next epoch time
            
            // distribute rewards to each recipient
            for ( uint i = 0; i < info.length; i++ ) {
                if ( info[ i ].rate > 0 ) {
                    ITreasury( treasury ).mintRewards( // mint and send from treasury
                        info[ i ].recipient, 
                        nextRewardAt( info[ i ].rate ) 
                    );
                    adjust( i ); // check for adjustment
                }
            }
            return true;
        } else { 
            return false; 
        }
    }
    
    
    
    /* ====== INTERNAL FUNCTIONS ====== */

    /**
        @notice increment reward rate for collector
     */
    function adjust( uint _index ) internal {
        Adjust memory adjustment = adjustments[ _index ];
        if ( adjustment.rate != 0 ) {
            if ( adjustment.add ) { // if rate should increase
                info[ _index ].rate = info[ _index ].rate.add( adjustment.rate ); // raise rate
                if ( info[ _index ].rate >= adjustment.target ) { // if target met
                    adjustments[ _index ].rate = 0; // turn off adjustment
                }
            } else { // if rate should decrease
                info[ _index ].rate = info[ _index ].rate.sub( adjustment.rate ); // lower rate
                if ( info[ _index ].rate <= adjustment.target ) { // if target met
                    adjustments[ _index ].rate = 0; // turn off adjustment
                }
            }
        }
    }
    
    
    
    /* ====== VIEW FUNCTIONS ====== */

    /**
        @notice view function for next reward at given rate
        @param _rate uint
        @return uint
     */
    function nextRewardAt( uint _rate ) public view returns ( uint ) {
        return IERC20( OHM ).totalSupply().mul( _rate ).div( 1000000 );
    }

    /**
        @notice view function for next reward for specified address
        @param _recipient address
        @return uint
     */
    function nextRewardFor( address _recipient ) public view returns ( uint ) {
        uint reward;
        for ( uint i = 0; i < info.length; i++ ) {
            if ( info[ i ].recipient == _recipient ) {
                reward = nextRewardAt( info[ i ].rate );
            }
        }
        return reward;
    }
    
    
    
    /* ====== POLICY FUNCTIONS ====== */

    /**
        @notice adds recipient for distributions
        @param _recipient address
        @param _rewardRate uint
     */
    function addRecipient( address _recipient, uint _rewardRate ) external onlyPolicy() {
        require( _recipient != address(0) );
        info.push( Info({
            recipient: _recipient,
            rate: _rewardRate
        }));
    }

    /**
        @notice removes recipient for distributions
        @param _index uint
        @param _recipient address
     */
    function removeRecipient( uint _index, address _recipient ) external onlyPolicy() {
        require( _recipient == info[ _index ].recipient );
        info[ _index ].recipient = address(0);
        info[ _index ].rate = 0;
    }

    /**
        @notice set adjustment info for a collector's reward rate
        @param _index uint
        @param _add bool
        @param _rate uint
        @param _target uint
     */
    function setAdjustment( uint _index, bool _add, uint _rate, uint _target ) external onlyPolicy() {
        adjustments[ _index ] = Adjust({
            add: _add,
            rate: _rate,
            target: _target
        });
    }
}
        

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_treasury","internalType":"address"},{"type":"address","name":"_ohm","internalType":"address"},{"type":"uint32","name":"_epochLength","internalType":"uint32"},{"type":"uint32","name":"_nextEpochTime","internalType":"uint32"}]},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"OHM","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addRecipient","inputs":[{"type":"address","name":"_recipient","internalType":"address"},{"type":"uint256","name":"_rewardRate","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"add","internalType":"bool"},{"type":"uint256","name":"rate","internalType":"uint256"},{"type":"uint256","name":"target","internalType":"uint256"}],"name":"adjustments","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"distribute","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"epochLength","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"rate","internalType":"uint256"},{"type":"address","name":"recipient","internalType":"address"}],"name":"info","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"nextEpochTime","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"nextRewardAt","inputs":[{"type":"uint256","name":"_rate","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"nextRewardFor","inputs":[{"type":"address","name":"_recipient","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"policy","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"pullPolicy","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"pushPolicy","inputs":[{"type":"address","name":"newPolicy_","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removeRecipient","inputs":[{"type":"uint256","name":"_index","internalType":"uint256"},{"type":"address","name":"_recipient","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renouncePolicy","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setAdjustment","inputs":[{"type":"uint256","name":"_index","internalType":"uint256"},{"type":"bool","name":"_add","internalType":"bool"},{"type":"uint256","name":"_rate","internalType":"uint256"},{"type":"uint256","name":"_target","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"treasury","inputs":[]}]
              

Contract Creation Code

0x60e060405234801561001057600080fd5b5060405161110b38038061110b8339818101604052608081101561003357600080fd5b5080516020820151604080840151606090940151600080546001600160a01b031916331780825592519495939491926001600160a01b0316917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a36001600160a01b0384166100a457600080fd5b6001600160601b0319606085901b1660a0526001600160a01b0383166100c957600080fd5b606083811b6001600160601b03191660805260e083901b6001600160e01b03191660c0526001805463ffffffff60a01b1916600160a01b63ffffffff9485160217905560a0516001600160a01b0390941694509290921c9116610fb7610154600039806103ee52806107ac52508061051c528061082852508061068b52806106e25250610fb76000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c8063a15ad07711610097578063c9fa8b2a11610066578063c9fa8b2a1461027e578063e4fc6b6d1461029b578063f7982243146102b7578063fe3fbbad146102e357610100565b8063a15ad0771461020b578063a4b2398014610231578063a6c41fec14610239578063bc3b2b121461024157610100565b806357d775f8116100d357806357d775f8146101c05780635beede08146101c85780635db854b0146101d257806361d027b31461020357610100565b80630505c8c9146101055780631da56eb3146101295780632e3405991461014a57806336d33f4414610188575b600080fd5b61010d61030f565b604080516001600160a01b039092168252519081900360200190f35b61013161031f565b6040805163ffffffff9092168252519081900360200190f35b6101676004803603602081101561016057600080fd5b5035610332565b604080519283526001600160a01b0390911660208301528051918290030190f35b6101ae6004803603602081101561019e57600080fd5b50356001600160a01b0316610369565b60408051918252519081900360200190f35b6101316103ec565b6101d0610410565b005b6101d0600480360360808110156101e857600080fd5b50803590602081013515159060408101359060600135610488565b61010d61051a565b6101d06004803603602081101561022157600080fd5b50356001600160a01b031661053e565b6101d06105f2565b61010d610689565b61025e6004803603602081101561025757600080fd5b50356106ad565b604080519315158452602084019290925282820152519081900360600190f35b6101ae6004803603602081101561029457600080fd5b50356106d3565b6102a3610777565b604080519115158252519081900360200190f35b6101d0600480360360408110156102cd57600080fd5b506001600160a01b038135169060200135610918565b6101d0600480360360408110156102f957600080fd5b50803590602001356001600160a01b0316610a0d565b6000546001600160a01b03165b90565b600154600160a01b900463ffffffff1681565b6003818154811061034257600080fd5b6000918252602090912060029091020180546001909101549091506001600160a01b031682565b60008060005b6003548110156103e557836001600160a01b03166003828154811061039057fe5b60009182526020909120600160029092020101546001600160a01b031614156103dd576103da600382815481106103c357fe5b9060005260206000209060020201600001546106d3565b91505b60010161036f565b5092915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b0316331461042757600080fd5b600154600080546040516001600160a01b0393841693909116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600154600080546001600160a01b0319166001600160a01b03909216919091179055565b6000546001600160a01b031633146104d5576040805162461bcd60e51b81526020600482018190526024820152600080516020610f62833981519152604482015290519081900360640190fd5b6040805160608101825293151584526020808501938452848201928352600095865260029081905294209251835460ff19169015151783559051600183015551910155565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000546001600160a01b0316331461058b576040805162461bcd60e51b81526020600482018190526024820152600080516020610f62833981519152604482015290519081900360640190fd5b6001600160a01b0381166105d05760405162461bcd60e51b8152600401808060200182810382526026815260200180610f1b6026913960400191505060405180910390fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b0316331461063f576040805162461bcd60e51b81526020600482018190526024820152600080516020610f62833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b7f000000000000000000000000000000000000000000000000000000000000000081565b600260208190526000918252604090912080546001820154919092015460ff9092169183565b6000610771620f424061076b847f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561073957600080fd5b505afa15801561074d573d6000803e3d6000fd5b505050506040513d602081101561076357600080fd5b505190610afa565b90610b5a565b92915050565b60015460009063ffffffff428116600160a01b9092041611610910576001546107d29063ffffffff600160a01b9091048116907f000000000000000000000000000000000000000000000000000000000000000090610b9c16565b600160146101000a81548163ffffffff021916908363ffffffff16021790555060005b6003548110156109065760006003828154811061080e57fe5b90600052602060002090600202016000015411156108fe577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636a20de926003838154811061086257fe5b906000526020600020906002020160010160009054906101000a90046001600160a01b0316610897600385815481106103c357fe5b6040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050600060405180830381600087803b1580156108dd57600080fd5b505af11580156108f1573d6000803e3d6000fd5b505050506108fe81610bff565b6001016107f5565b506001905061031c565b50600061031c565b6000546001600160a01b03163314610965576040805162461bcd60e51b81526020600482018190526024820152600080516020610f62833981519152604482015290519081900360640190fd5b6001600160a01b03821661097857600080fd5b604080518082019091529081526001600160a01b03918216602082019081526003805460018101825560009190915291517fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b600290930292830155517fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c90910180546001600160a01b03191691909216179055565b6000546001600160a01b03163314610a5a576040805162461bcd60e51b81526020600482018190526024820152600080516020610f62833981519152604482015290519081900360640190fd5b60038281548110610a6757fe5b60009182526020909120600160029092020101546001600160a01b03828116911614610a9257600080fd5b600060038381548110610aa157fe5b906000526020600020906002020160010160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600060038381548110610ae557fe5b60009182526020909120600290910201555050565b600082610b0957506000610771565b82820282848281610b1657fe5b0414610b535760405162461bcd60e51b8152600401808060200182810382526021815260200180610f416021913960400191505060405180910390fd5b9392505050565b6000610b5383836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250610d64565b600082820163ffffffff8085169082161015610b53576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b610c07610ef7565b506000818152600260208181526040928390208351606081018552815460ff16151581526001820154928101839052920154928201929092529015610d6057805115610cd957610c79816020015160038481548110610c6257fe5b600091825260209091206002909102015490610e06565b60038381548110610c8657fe5b600091825260209091206002909102015560408101516003805484908110610caa57fe5b90600052602060002090600202016000015410610cd4576000828152600260205260408120600101555b610d60565b610d05816020015160038481548110610cee57fe5b600091825260209091206002909102015490610e60565b60038381548110610d1257fe5b600091825260209091206002909102015560408101516003805484908110610d3657fe5b90600052602060002090600202016000015411610d60576000828152600260205260408120600101555b5050565b60008183610df05760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610db5578181015183820152602001610d9d565b50505050905090810190601f168015610de25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581610dfc57fe5b0495945050505050565b600082820183811015610b53576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000610b5383836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525060008184841115610eef5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610db5578181015183820152602001610d9d565b505050900390565b60405180606001604052806000151581526020016000815260200160008152509056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572a26469706673582212206e26f07dfb1359efd9ff8cbbcdd756b42fade8f7c6917ba28920843aa4c2790464736f6c63430007050033000000000000000000000000e2adcd126b4275cd75e72ff7ddc8cf7e43fc13d4000000000000000000000000e685d21b7b0fc7a248a6a8e03b8db22d013aa2ee00000000000000000000000000000000000000000000000000000000000070800000000000000000000000000000000000000000000000000000000061d0b2c0

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106101005760003560e01c8063a15ad07711610097578063c9fa8b2a11610066578063c9fa8b2a1461027e578063e4fc6b6d1461029b578063f7982243146102b7578063fe3fbbad146102e357610100565b8063a15ad0771461020b578063a4b2398014610231578063a6c41fec14610239578063bc3b2b121461024157610100565b806357d775f8116100d357806357d775f8146101c05780635beede08146101c85780635db854b0146101d257806361d027b31461020357610100565b80630505c8c9146101055780631da56eb3146101295780632e3405991461014a57806336d33f4414610188575b600080fd5b61010d61030f565b604080516001600160a01b039092168252519081900360200190f35b61013161031f565b6040805163ffffffff9092168252519081900360200190f35b6101676004803603602081101561016057600080fd5b5035610332565b604080519283526001600160a01b0390911660208301528051918290030190f35b6101ae6004803603602081101561019e57600080fd5b50356001600160a01b0316610369565b60408051918252519081900360200190f35b6101316103ec565b6101d0610410565b005b6101d0600480360360808110156101e857600080fd5b50803590602081013515159060408101359060600135610488565b61010d61051a565b6101d06004803603602081101561022157600080fd5b50356001600160a01b031661053e565b6101d06105f2565b61010d610689565b61025e6004803603602081101561025757600080fd5b50356106ad565b604080519315158452602084019290925282820152519081900360600190f35b6101ae6004803603602081101561029457600080fd5b50356106d3565b6102a3610777565b604080519115158252519081900360200190f35b6101d0600480360360408110156102cd57600080fd5b506001600160a01b038135169060200135610918565b6101d0600480360360408110156102f957600080fd5b50803590602001356001600160a01b0316610a0d565b6000546001600160a01b03165b90565b600154600160a01b900463ffffffff1681565b6003818154811061034257600080fd5b6000918252602090912060029091020180546001909101549091506001600160a01b031682565b60008060005b6003548110156103e557836001600160a01b03166003828154811061039057fe5b60009182526020909120600160029092020101546001600160a01b031614156103dd576103da600382815481106103c357fe5b9060005260206000209060020201600001546106d3565b91505b60010161036f565b5092915050565b7f000000000000000000000000000000000000000000000000000000000000708081565b6001546001600160a01b0316331461042757600080fd5b600154600080546040516001600160a01b0393841693909116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600154600080546001600160a01b0319166001600160a01b03909216919091179055565b6000546001600160a01b031633146104d5576040805162461bcd60e51b81526020600482018190526024820152600080516020610f62833981519152604482015290519081900360640190fd5b6040805160608101825293151584526020808501938452848201928352600095865260029081905294209251835460ff19169015151783559051600183015551910155565b7f000000000000000000000000e2adcd126b4275cd75e72ff7ddc8cf7e43fc13d481565b6000546001600160a01b0316331461058b576040805162461bcd60e51b81526020600482018190526024820152600080516020610f62833981519152604482015290519081900360640190fd5b6001600160a01b0381166105d05760405162461bcd60e51b8152600401808060200182810382526026815260200180610f1b6026913960400191505060405180910390fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b0316331461063f576040805162461bcd60e51b81526020600482018190526024820152600080516020610f62833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b7f000000000000000000000000e685d21b7b0fc7a248a6a8e03b8db22d013aa2ee81565b600260208190526000918252604090912080546001820154919092015460ff9092169183565b6000610771620f424061076b847f000000000000000000000000e685d21b7b0fc7a248a6a8e03b8db22d013aa2ee6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561073957600080fd5b505afa15801561074d573d6000803e3d6000fd5b505050506040513d602081101561076357600080fd5b505190610afa565b90610b5a565b92915050565b60015460009063ffffffff428116600160a01b9092041611610910576001546107d29063ffffffff600160a01b9091048116907f000000000000000000000000000000000000000000000000000000000000708090610b9c16565b600160146101000a81548163ffffffff021916908363ffffffff16021790555060005b6003548110156109065760006003828154811061080e57fe5b90600052602060002090600202016000015411156108fe577f000000000000000000000000e2adcd126b4275cd75e72ff7ddc8cf7e43fc13d46001600160a01b0316636a20de926003838154811061086257fe5b906000526020600020906002020160010160009054906101000a90046001600160a01b0316610897600385815481106103c357fe5b6040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050600060405180830381600087803b1580156108dd57600080fd5b505af11580156108f1573d6000803e3d6000fd5b505050506108fe81610bff565b6001016107f5565b506001905061031c565b50600061031c565b6000546001600160a01b03163314610965576040805162461bcd60e51b81526020600482018190526024820152600080516020610f62833981519152604482015290519081900360640190fd5b6001600160a01b03821661097857600080fd5b604080518082019091529081526001600160a01b03918216602082019081526003805460018101825560009190915291517fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b600290930292830155517fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c90910180546001600160a01b03191691909216179055565b6000546001600160a01b03163314610a5a576040805162461bcd60e51b81526020600482018190526024820152600080516020610f62833981519152604482015290519081900360640190fd5b60038281548110610a6757fe5b60009182526020909120600160029092020101546001600160a01b03828116911614610a9257600080fd5b600060038381548110610aa157fe5b906000526020600020906002020160010160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600060038381548110610ae557fe5b60009182526020909120600290910201555050565b600082610b0957506000610771565b82820282848281610b1657fe5b0414610b535760405162461bcd60e51b8152600401808060200182810382526021815260200180610f416021913960400191505060405180910390fd5b9392505050565b6000610b5383836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250610d64565b600082820163ffffffff8085169082161015610b53576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b610c07610ef7565b506000818152600260208181526040928390208351606081018552815460ff16151581526001820154928101839052920154928201929092529015610d6057805115610cd957610c79816020015160038481548110610c6257fe5b600091825260209091206002909102015490610e06565b60038381548110610c8657fe5b600091825260209091206002909102015560408101516003805484908110610caa57fe5b90600052602060002090600202016000015410610cd4576000828152600260205260408120600101555b610d60565b610d05816020015160038481548110610cee57fe5b600091825260209091206002909102015490610e60565b60038381548110610d1257fe5b600091825260209091206002909102015560408101516003805484908110610d3657fe5b90600052602060002090600202016000015411610d60576000828152600260205260408120600101555b5050565b60008183610df05760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610db5578181015183820152602001610d9d565b50505050905090810190601f168015610de25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581610dfc57fe5b0495945050505050565b600082820183811015610b53576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000610b5383836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525060008184841115610eef5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610db5578181015183820152602001610d9d565b505050900390565b60405180606001604052806000151581526020016000815260200160008152509056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572a26469706673582212206e26f07dfb1359efd9ff8cbbcdd756b42fade8f7c6917ba28920843aa4c2790464736f6c63430007050033