ETH Price: $1,757.49 (+11.25%)
 
Transaction Hash
Method
Block
From
To
Next Epoch164213032023-01-16 19:00:23827 days ago1673895623IN
0x91E5552b...0d09D6833
0 ETH0.0012351526.64390448
End Epoch164213022023-01-16 19:00:11827 days ago1673895611IN
0x91E5552b...0d09D6833
0 ETH0.0409157624.54733473
End Epoch164212032023-01-16 18:40:11827 days ago1673894411IN
0x91E5552b...0d09D6833
0 ETH0.0258550621.55170879
End Epoch164210532023-01-16 18:10:11827 days ago1673892611IN
0x91E5552b...0d09D6833
0 ETH0.0361526330.13794625
End Epoch164210032023-01-16 18:00:11827 days ago1673892011IN
0x91E5552b...0d09D6833
0 ETH0.0380513731.71643342
End Epoch164208052023-01-16 17:20:11827 days ago1673889611IN
0x91E5552b...0d09D6833
0 ETH0.0020130632.34048475
End Epoch164207552023-01-16 17:10:11827 days ago1673889011IN
0x91E5552b...0d09D6833
0 ETH0.0023879940.26023765
End Epoch164207052023-01-16 17:00:11827 days ago1673888411IN
0x91E5552b...0d09D6833
0 ETH0.0015015525.52101262
End Epoch164205052023-01-16 16:20:11827 days ago1673886011IN
0x91E5552b...0d09D6833
0 ETH0.0016437823.27943508
End Epoch164204552023-01-16 16:10:11827 days ago1673885411IN
0x91E5552b...0d09D6833
0 ETH0.0020240127.33858207
End Epoch164204102023-01-16 16:01:11827 days ago1673884871IN
0x91E5552b...0d09D6833
0 ETH0.0027549937.21212423
Next Epoch163495912023-01-06 18:40:23837 days ago1673030423IN
0x91E5552b...0d09D6833
0 ETH0.0017471537.68831057
End Epoch163495902023-01-06 18:40:11837 days ago1673030411IN
0x91E5552b...0d09D6833
0 ETH0.0014996238.99076797
Next Epoch162994352022-12-30 18:40:35844 days ago1672425635IN
0x91E5552b...0d09D6833
0 ETH0.00083818.07685164
End Epoch162994332022-12-30 18:40:11844 days ago1672425611IN
0x91E5552b...0d09D6833
0 ETH0.0006500216.90085116
Next Epoch162492762022-12-23 18:40:23851 days ago1671820823IN
0x91E5552b...0d09D6833
0 ETH0.0007509816.19958175
End Epoch162492752022-12-23 18:40:11851 days ago1671820811IN
0x91E5552b...0d09D6833
0 ETH0.0006339916.48400208
Claim161999612022-12-16 21:32:47858 days ago1671226367IN
0x91E5552b...0d09D6833
0 ETH0.0013211417.39492369
Next Epoch161993332022-12-16 19:25:11858 days ago1671218711IN
0x91E5552b...0d09D6833
0 ETH0.0009079819.58642427
End Epoch161991912022-12-16 18:56:35858 days ago1671216995IN
0x91E5552b...0d09D6833
0 ETH0.0050147218.31186971
Claim161986502022-12-16 17:07:59858 days ago1671210479IN
0x91E5552b...0d09D6833
0 ETH0.0021375627.86441855
Next Epoch161985122022-12-16 16:40:23858 days ago1671208823IN
0x91E5552b...0d09D6833
0 ETH0.0018681523.19022544
End Epoch161985112022-12-16 16:40:11858 days ago1671208811IN
0x91E5552b...0d09D6833
0 ETH0.0106482622.46023731

Latest 13 internal transactions

Advanced mode:
Parent Transaction Hash Method Block
From
To
Transfer166375602023-02-15 23:57:11797 days ago1676505431
0x91E5552b...0d09D6833
0.0005 ETH
Swap Exact ETH F...164213022023-01-16 19:00:11827 days ago1673895611
0x91E5552b...0d09D6833
0.01 ETH
Swap Exact ETH F...164212032023-01-16 18:40:11827 days ago1673894411
0x91E5552b...0d09D6833
0.01 ETH
Swap Exact ETH F...164210532023-01-16 18:10:11827 days ago1673892611
0x91E5552b...0d09D6833
0.01 ETH
Swap Exact ETH F...164210032023-01-16 18:00:11827 days ago1673892011
0x91E5552b...0d09D6833
0.01 ETH
Transfer163780652023-01-10 18:01:11833 days ago1673373671
0x91E5552b...0d09D6833
0.005 ETH
Transfer163780302023-01-10 17:53:59833 days ago1673373239
0x91E5552b...0d09D6833
0.005 ETH
Swap Exact ETH F...161991912022-12-16 18:56:35858 days ago1671216995
0x91E5552b...0d09D6833
0.51 ETH
Swap Exact ETH F...161985112022-12-16 16:40:11858 days ago1671208811
0x91E5552b...0d09D6833
0.025 ETH
Transfer161698802022-12-12 16:41:11862 days ago1670863271
0x91E5552b...0d09D6833
0.25 ETH
Transfer161698602022-12-12 16:37:11862 days ago1670863031
0x91E5552b...0d09D6833
0.25 ETH
Transfer161497712022-12-09 21:16:47865 days ago1670620607
0x91E5552b...0d09D6833
0.01 ETH
Transfer161497622022-12-09 21:14:59865 days ago1670620499
0x91E5552b...0d09D6833
0.025 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
MerkleRewardsDistributor

Compiler Version
v0.8.14+commit.80d49f37

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 9 : MerkleRewardsDistributor.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.14;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Router02.sol";

/**
 *  @title A Rewards Distributor Contract
 *  @notice A rewards distribution contract using a Merkle Tree to verify the amount and
 *          address of the user claiming ERC20 tokens
 *  @dev Functions are intended to be triggered on a specific timeframe (epoch) via a back-end
 *       service
 */
contract MerkleRewardsDistributor is Ownable, ReentrancyGuard {

    //
    // Constants ==================================================================================
    //

    uint16 public constant BPS_MAX = 10000;    

    //
    // State ======================================================================================
    //

    IERC20 public tokenContract;
    IUniswapV2Router02 public routerContract;

    bool public betweenEpochs;
    address public adminAddress;
    address public daoAddress;
    address public treasuryAddress;
    bytes32 public merkleRoot;
    /// @dev Treasury fee percentage expressed in basis points
    uint16 public treasuryFeeBps;
    uint256 public currentEpoch;
    /// @dev Cumulative amount of fees allocated to treasury during current epoch
    uint256 public treasuryFees;    
    
    uint256 public minStakeAmount = 2000 * 1e18;
    uint256 public swapTimeout = 15 minutes;

    mapping(bytes32 => bool) public claimed;

    //
    // Constructor ================================================================================
    //

    constructor(
        address _adminAddress,
        address _treasuryAddress,
        address _daoAddress,
        address tokenAddress,
        address routerAddress
    ) {
        adminAddress = _adminAddress;
        treasuryAddress = _treasuryAddress;
        daoAddress = _daoAddress;
        tokenContract = IERC20(tokenAddress);
        routerContract = IUniswapV2Router02(routerAddress);
    }

    //
    // Receive function ===========================================================================
    //

    receive() external payable {
        // Empty
    }

    //
    // Modifiers ==================================================================================
    //

    modifier claimsEnabled() {
        if(betweenEpochs) revert ClaimsDisabledUntilNextEpoch();
        _;
    }

    modifier onlyAdmin() {
        if(msg.sender != adminAddress) revert OnlyAdmin();
        _;
    }

    modifier onlyDao() {
        if(msg.sender != daoAddress) revert OnlyDao();
        _;
    }

    //
    // External functions =========================================================================
    //

    /**
     * @notice Transfers tokens to the claimer address if he was included in the Merkle Tree with
     *         the specified index
     */
    function claim(
        uint256 amountToClaim,
        bytes32[] calldata merkleProof
    ) external nonReentrant claimsEnabled {
        bytes32 leaf = toLeaf(currentEpoch, msg.sender, amountToClaim);
        /// @dev make sure the merkle proof validates the claim
        if(!MerkleProof.verify(merkleProof, merkleRoot, leaf)) revert InvalidMerkleProof();
        /// @dev cannot claim same leaf more than oncer per epoch
        if(claimed[leaf]) revert RewardAlreadyClaimed();
        
        claimed[leaf] = true;

        tokenContract.transfer(msg.sender, amountToClaim);

        emit Claimed(msg.sender, currentEpoch, amountToClaim);
    }

    function claimsDisabled() external view returns (bool) {
        return betweenEpochs;
    }

    /**
     *  @notice Ends the current epoch, marks all attributed tokens, ETH and when the epoch has ended
     */
    function endEpoch(
        uint256 epochNumber,
        uint256 ethAttributed,
        address[] memory ethSwapPath,
        uint256 ethReturnMin,
        address[] memory tokensAttributed,
        uint256[] memory amountsAttributed,
        address[][] memory swapPaths,
        uint256[] memory amountsOutMin
    ) external onlyAdmin {
        /// @dev make sure the caller knows which epoch they're ending
        if(epochNumber != currentEpoch) revert IncorrectEpoch();

        if(ethAttributed > address(this).balance) {
            revert InsufficientEthBalance(ethAttributed, address(this).balance);
        }
        
        /// @dev make sure our input arrays have matching lengths
        uint256 tokenCount = tokensAttributed.length;
        if(amountsAttributed.length != tokenCount
            || swapPaths.length != tokenCount
            || amountsOutMin.length != tokenCount
        ) revert MismatchedArrayLengths();

        /// @dev pause claims until our the next/new merkle root set
        betweenEpochs = true;

        /// @dev emit event and increment currentEpoch
        emit EpochEnded(currentEpoch, block.timestamp);

        if(ethAttributed > 0 || tokensAttributed.length > 0) {
            /// @dev Execute the token/ETH swaps
            swapMultiple(
                ethAttributed,
                ethSwapPath,
                ethReturnMin,
                tokensAttributed,
                amountsAttributed,
                swapPaths,
                amountsOutMin
            );
        }

        if(treasuryFees > 0) {
            depositTreasuryFees();
        }
    }

    function nextEpoch(bytes32 newMerkleRoot, bytes memory newMerkleCDI) external onlyAdmin {
        if(!betweenEpochs) revert InvalidRequest("Epoch in progress");
        currentEpoch += 1;
        betweenEpochs = false;
        treasuryFees = 0;
        setMerkleRoot(newMerkleRoot, newMerkleCDI);
        emit EpochStarted(currentEpoch);
    }

    function setAdminAddress(address _adminAddress) external onlyOwner {
        emit AdminAddressUpdated(adminAddress, _adminAddress);
        adminAddress = _adminAddress;
    }

    function setDaoAddress(address _daoAddress) external onlyOwner {
        emit DaoAddressUpdated(daoAddress, _daoAddress);
        daoAddress = _daoAddress;
    }

    function setMinStakeAmount(uint256 _minStakeAmount) external onlyDao {
        emit MinStakeAmountUpdated(minStakeAmount, _minStakeAmount);
        minStakeAmount = _minStakeAmount;
    }

    function setRouterContract(address _routerContract) external onlyOwner {
        emit RouterContractUpdated(address(routerContract), _routerContract);
        routerContract = IUniswapV2Router02(_routerContract);
    }

    /**
     * @notice Sets the swap timeout for ERC20 token swaps via the router contract
     * @param _swapTimeout the new timeout expressed in seconds
     */
    function setSwapTimeout(uint256 _swapTimeout) external onlyOwner {
        emit SwapTimeoutUpdated(swapTimeout, _swapTimeout);
        swapTimeout = _swapTimeout;
    }

    /**
     * @notice Updates the treasury fee recipient address
     * @param _treasuryAddress the new treasury address
     */
    function setTreasuryAddress(address _treasuryAddress) external onlyOwner {
        emit TreasuryAddressUpdated(treasuryAddress, _treasuryAddress);
        treasuryAddress = _treasuryAddress;
    }

    /**
     * @notice Updates the treasury fee percentage
     * @param _treasuryFeeBps the fee percentage expressed in basis points e.g. 650 is 6.5%
     */
    function setTreasuryFeeBps(uint16 _treasuryFeeBps) external onlyDao {
        if(_treasuryFeeBps > BPS_MAX) revert InvalidTreasuryFee();
        emit TreasuryFeeUpdated(treasuryFeeBps, _treasuryFeeBps);
        treasuryFeeBps = _treasuryFeeBps;
    }

    //
    // Internal functions =========================================================================
    //

    /**
     * @notice Transfer cumulative treasury fees if any to `treasuryAddress`
     */
    function depositTreasuryFees() internal {
        uint256 _treasuryFees = treasuryFees;
        treasuryFees = 0;
        tokenContract.transfer(treasuryAddress, _treasuryFees);
        emit DepositedTreasuryFees(treasuryAddress, _treasuryFees);
    }

    /**
     *  @notice Calculates a leaf of the tree in bytes format (to be passed for verification).
     *      The leaf includes the epoch number which means they are unique across epochs
     *      for identical addresses and claim amounts. Leaves are double-hashed to prevent
     *      second preimage attacks, see:
     * 
     *      https://flawed.net.nz/2018/02/21/attacking-merkle-trees-with-a-second-preimage-attack/
     */
    function toLeaf(uint256 epoch, address addr, uint256 amount)
        internal
        pure
        returns (bytes32) {
        return keccak256(
            bytes.concat(
                keccak256(
                    abi.encode(epoch, addr, amount)
                )
            )
        );
    }

    /**
     * @param newMerkleRoot the newly calculated root of the tree after all user info is updated
     *        at the end of an epoch
     * @param newMerkleCDI the new CDI on IPFS where the file to rebuild the Merkle Tree is
     *        contained
     */
    function setMerkleRoot(bytes32 newMerkleRoot, bytes memory newMerkleCDI) internal {
        merkleRoot = newMerkleRoot;
        emit MerkleProofCIDUpdated(newMerkleCDI);
    }

    /**
     *  @notice Does a bunch of swaps with all tokens in tokensIn. Also swaps ETH for tokenContract
     *          if transaction value > 0.
     *  @dev amountsOutMin array should be passed with the right minimum amounts calculated
     *       otherwise the transaction would fail.
     */
    function swapMultiple(
        uint256 ethAttributed,
        address[] memory ethSwapPath,
        uint256 ethReturnMin,
        address[] memory tokensAttributed,
        uint256[] memory amountsAttributed,
        address[][] memory swapPaths,
        uint256[] memory amountsOutMin
    ) internal {

        if (ethAttributed > 0) {
            _swapEth(ethAttributed, ethSwapPath, ethReturnMin);
        }

        address currentTokenToSwap;
        uint256 tokenAmount;

        /// @dev iterate over tokens and swap each of them
        for (uint256 i = 0; i < tokensAttributed.length;) {
            
            currentTokenToSwap = tokensAttributed[i];
            tokenAmount = amountsAttributed[i];

            if(tokenAmount > IERC20(currentTokenToSwap).balanceOf(address(this))) {
                revert InsufficientTokenBalance(
                    currentTokenToSwap,
                    tokenAmount,
                    IERC20(currentTokenToSwap).balanceOf(address(this))
                );
            }

            if(currentTokenToSwap == address(tokenContract)) {
                /// @dev no swap needs to occur in this case
                _finalizeErc20Swap(currentTokenToSwap, tokenAmount);
            }
            else {
                IERC20(currentTokenToSwap).approve(
                    address(routerContract),
                    tokenAmount
                );

                _swapErc20(tokenAmount, amountsOutMin[i], swapPaths[i]);
            }

            /// @dev gas savings, can't overflow bc constrained by our array's length
            unchecked {
                i++;
            }
        }
    }

    //
    // Private functions ==========================================================================
    //

    /**
     * @notice Possibly apply treasury fee to swapped token amount and emit swap event
     * @param tokenAmount the amount of reward tokens received from the token/Eth swap
     */
    function _applyFee(uint256 tokenAmount) private returns (uint256) {
        if(treasuryFeeBps > 0) {
            uint256 feeAmount = treasuryFeeBps * tokenAmount / BPS_MAX;
            tokenAmount -= feeAmount;
            treasuryFees += feeAmount;
            emit TreasuryFeeTaken(currentEpoch, feeAmount);
        }

        return tokenAmount;
    }

    function _finalizeErc20Swap(address tokenAddress, uint256 tokenAmount) private {
        uint256 netTokenAmount = _applyFee(tokenAmount);
        emit TokensSwapped(tokenAmount, netTokenAmount, currentEpoch, tokenAddress);
    }

    /**
     *  @dev Swaps tokens in path with the recipient being this contract
     *  @dev The optimal path relies on being accepted externally
     */
    function _swapErc20(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] memory path
    ) private {
        uint256[] memory amounts = routerContract.swapExactTokensForTokens(
            amountIn,
            amountOutMin,
            path,
            address(this),
            block.timestamp + swapTimeout
        );

        _finalizeErc20Swap(path[0], amounts[1]);
    }

    function _swapEth(uint256 ethAmount, address[] memory ethSwapPath, uint256 ethReturnMin) private {
        uint256[] memory amounts = routerContract.swapExactETHForTokens{
            value: ethAmount
        }(
            ethReturnMin,
            ethSwapPath,
            address(this),
            block.timestamp + swapTimeout
        );

        uint256 netTokenAmount = _applyFee(amounts[1]);

        emit EthSwapped(amounts[1], netTokenAmount, currentEpoch);
    }

    //
    // Errors/events ==============================================================================
    //

    error ClaimsDisabledUntilNextEpoch();
    error IncorrectEpoch();
    error InvalidEpoch();
    error InvalidMerkleProof();
    error InvalidRequest(string msg);
    error InvalidTreasuryFee();
    error InsufficientEthBalance(uint256 required, uint256 actual);
    error InsufficientTokenBalance(address token, uint256 required, uint256 actual);
    error MismatchedArrayLengths();
    error NoTokensAttributed();
    error OnlyAdmin();
    error OnlyDao();
    error RewardAlreadyClaimed();

    event AdminAddressUpdated(address indexed from, address indexed to);
    event Claimed(address indexed account, uint256 epoch, uint256 amount);
    event DaoAddressUpdated(address indexed from, address indexed to);
    event DepositedTreasuryFees(address indexed addr, uint256 amount);
    event EpochEnded(uint256 endedEpochNum, uint256 timestamp);
    event EpochStarted(uint256 epochNumber);
    event EthSwapped(uint256 swapAmountOut, uint256 receivedTokens, uint256 epoch);
    event MerkleProofCIDUpdated(bytes newMerkleCDI);
    event MinStakeAmountUpdated(uint256 from, uint256 to);
    event RouterContractUpdated(address indexed from, address indexed to);
    event SwapTimeoutUpdated(uint256 from, uint256 to);
    event TokensSwapped(uint256 swapAmountOut, uint256 receivedTokens, uint256 epoch, address indexed tokenAddress);
    event TreasuryAddressUpdated(address indexed from, address indexed to);
    event TreasuryFeeTaken(uint256 epoch, uint256 amount);
    event TreasuryFeeUpdated(uint256 from, uint256 to);
}

File 2 of 9 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 3 of 9 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

File 4 of 9 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 5 of 9 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

File 6 of 9 : MerkleProof.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/MerkleProof.sol)

pragma solidity ^0.8.0;

/**
 * @dev These functions deal with verification of Merkle Trees proofs.
 *
 * The proofs can be generated using the JavaScript library
 * https://github.com/miguelmota/merkletreejs[merkletreejs].
 * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.
 *
 * See `test/utils/cryptography/MerkleProof.test.js` for some examples.
 */
library MerkleProof {
    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     */
    function verify(
        bytes32[] memory proof,
        bytes32 root,
        bytes32 leaf
    ) internal pure returns (bool) {
        return processProof(proof, leaf) == root;
    }

    /**
     * @dev Returns the rebuilt hash obtained by traversing a Merklee tree up
     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
     * hash matches the root of the tree. When processing the proof, the pairs
     * of leafs & pre-images are assumed to be sorted.
     *
     * _Available since v4.4._
     */
    function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            bytes32 proofElement = proof[i];
            if (computedHash <= proofElement) {
                // Hash(current computed hash + current element of the proof)
                computedHash = _efficientHash(computedHash, proofElement);
            } else {
                // Hash(current element of the proof + current computed hash)
                computedHash = _efficientHash(proofElement, computedHash);
            }
        }
        return computedHash;
    }

    function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
        assembly {
            mstore(0x00, a)
            mstore(0x20, b)
            value := keccak256(0x00, 0x40)
        }
    }
}

File 7 of 9 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }
}

File 8 of 9 : IUniswapV2Router01.sol
// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.6.2;

interface IUniswapV2Router01 {
    function factory() external pure returns (address);
    function WETH() external pure returns (address);

    function addLiquidity(
        address tokenA,
        address tokenB,
        uint amountADesired,
        uint amountBDesired,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external returns (uint amountA, uint amountB, uint liquidity);
    function addLiquidityETH(
        address token,
        uint amountTokenDesired,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external payable returns (uint amountToken, uint amountETH, uint liquidity);
    function removeLiquidity(
        address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external returns (uint amountA, uint amountB);
    function removeLiquidityETH(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external returns (uint amountToken, uint amountETH);
    function removeLiquidityWithPermit(
        address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountA, uint amountB);
    function removeLiquidityETHWithPermit(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountToken, uint amountETH);
    function swapExactTokensForTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
    function swapTokensForExactTokens(
        uint amountOut,
        uint amountInMax,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
    function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
        external
        payable
        returns (uint[] memory amounts);
    function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
        external
        returns (uint[] memory amounts);
    function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
        external
        returns (uint[] memory amounts);
    function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
        external
        payable
        returns (uint[] memory amounts);

    function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
    function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
    function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
    function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
    function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}

File 9 of 9 : IUniswapV2Router02.sol
// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.6.2;

import './IUniswapV2Router01.sol';

interface IUniswapV2Router02 is IUniswapV2Router01 {
    function removeLiquidityETHSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external returns (uint amountETH);
    function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountETH);

    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
    function swapExactETHForTokensSupportingFeeOnTransferTokens(
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external payable;
    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_adminAddress","type":"address"},{"internalType":"address","name":"_treasuryAddress","type":"address"},{"internalType":"address","name":"_daoAddress","type":"address"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"routerAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ClaimsDisabledUntilNextEpoch","type":"error"},{"inputs":[],"name":"IncorrectEpoch","type":"error"},{"inputs":[{"internalType":"uint256","name":"required","type":"uint256"},{"internalType":"uint256","name":"actual","type":"uint256"}],"name":"InsufficientEthBalance","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"required","type":"uint256"},{"internalType":"uint256","name":"actual","type":"uint256"}],"name":"InsufficientTokenBalance","type":"error"},{"inputs":[],"name":"InvalidEpoch","type":"error"},{"inputs":[],"name":"InvalidMerkleProof","type":"error"},{"inputs":[{"internalType":"string","name":"msg","type":"string"}],"name":"InvalidRequest","type":"error"},{"inputs":[],"name":"InvalidTreasuryFee","type":"error"},{"inputs":[],"name":"MismatchedArrayLengths","type":"error"},{"inputs":[],"name":"NoTokensAttributed","type":"error"},{"inputs":[],"name":"OnlyAdmin","type":"error"},{"inputs":[],"name":"OnlyDao","type":"error"},{"inputs":[],"name":"RewardAlreadyClaimed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"AdminAddressUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"epoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"DaoAddressUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"DepositedTreasuryFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"endedEpochNum","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"EpochEnded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"epochNumber","type":"uint256"}],"name":"EpochStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"swapAmountOut","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"receivedTokens","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"EthSwapped","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"newMerkleCDI","type":"bytes"}],"name":"MerkleProofCIDUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"from","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"to","type":"uint256"}],"name":"MinStakeAmountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"RouterContractUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"from","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"to","type":"uint256"}],"name":"SwapTimeoutUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"swapAmountOut","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"receivedTokens","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"epoch","type":"uint256"},{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"}],"name":"TokensSwapped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"TreasuryAddressUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"epoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TreasuryFeeTaken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"from","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"to","type":"uint256"}],"name":"TreasuryFeeUpdated","type":"event"},{"inputs":[],"name":"BPS_MAX","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"adminAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"betweenEpochs","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountToClaim","type":"uint256"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"claimed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimsDisabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"daoAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"epochNumber","type":"uint256"},{"internalType":"uint256","name":"ethAttributed","type":"uint256"},{"internalType":"address[]","name":"ethSwapPath","type":"address[]"},{"internalType":"uint256","name":"ethReturnMin","type":"uint256"},{"internalType":"address[]","name":"tokensAttributed","type":"address[]"},{"internalType":"uint256[]","name":"amountsAttributed","type":"uint256[]"},{"internalType":"address[][]","name":"swapPaths","type":"address[][]"},{"internalType":"uint256[]","name":"amountsOutMin","type":"uint256[]"}],"name":"endEpoch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"merkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minStakeAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"newMerkleRoot","type":"bytes32"},{"internalType":"bytes","name":"newMerkleCDI","type":"bytes"}],"name":"nextEpoch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"routerContract","outputs":[{"internalType":"contract IUniswapV2Router02","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_adminAddress","type":"address"}],"name":"setAdminAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_daoAddress","type":"address"}],"name":"setDaoAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minStakeAmount","type":"uint256"}],"name":"setMinStakeAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_routerContract","type":"address"}],"name":"setRouterContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_swapTimeout","type":"uint256"}],"name":"setSwapTimeout","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_treasuryAddress","type":"address"}],"name":"setTreasuryAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_treasuryFeeBps","type":"uint16"}],"name":"setTreasuryFeeBps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapTimeout","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenContract","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasuryAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"treasuryFeeBps","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"treasuryFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

6080604052686c6b935b8bbd400000600b55610384600c553480156200002457600080fd5b5060405162001e3338038062001e33833981016040819052620000479162000126565b6200005233620000b9565b60018055600480546001600160a01b03199081166001600160a01b0397881617909155600680548216958716959095179094556005805485169386169390931790925560028054841691851691909117905560038054909216921691909117905562000196565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200012157600080fd5b919050565b600080600080600060a086880312156200013f57600080fd5b6200014a8662000109565b94506200015a6020870162000109565b93506200016a6040870162000109565b92506200017a6060870162000109565b91506200018a6080870162000109565b90509295509295909350565b611c8d80620001a66000396000f3fe6080604052600436106101bb5760003560e01c80637983f13c116100ec578063c5f956af1161008a578063eb4af04511610064578063eb4af045146104df578063f1887684146104ff578063f2fde38b14610515578063fc6f94681461053557600080fd5b8063c5f956af14610474578063cc3c0f0614610494578063e80cfa5e146104c457600080fd5b806393821371116100c6578063938213711461040857806394de34f1146104285780639a3cac6a1461043e5780639a67430f1461045e57600080fd5b80637983f13c1461039e5780637d5a9b5c146103c95780638da5cb5b146103ea57600080fd5b8063430d8536116101595780636605bfda116101335780636605bfda146103335780636cc91bca14610353578063715018a614610373578063766718081461038857600080fd5b8063430d8536146102d35780634f72d846146102f357806355a373d61461031357600080fd5b80632c1e816d116101955780632c1e816d146102465780632eb4a7ab146102665780632f52ebb71461028a5780633eb6e846146102aa57600080fd5b806318dbf545146101c75780632131c68c146101e957806321405ba41461022657600080fd5b366101c257005b600080fd5b3480156101d357600080fd5b506101e76101e2366004611557565b610555565b005b3480156101f557600080fd5b50600554610209906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561023257600080fd5b506101e76102413660046115c9565b610601565b34801561025257600080fd5b506101e7610261366004611684565b6106f2565b34801561027257600080fd5b5061027c60075481565b60405190815260200161021d565b34801561029657600080fd5b506101e76102a536600461169f565b610778565b3480156102b657600080fd5b506102c061271081565b60405161ffff909116815260200161021d565b3480156102df57600080fd5b506101e76102ee36600461171e565b6109b3565b3480156102ff57600080fd5b50600354610209906001600160a01b031681565b34801561031f57600080fd5b50600254610209906001600160a01b031681565b34801561033f57600080fd5b506101e761034e366004611684565b610a1e565b34801561035f57600080fd5b506101e761036e366004611684565b610aa4565b34801561037f57600080fd5b506101e7610b2a565b34801561039457600080fd5b5061027c60095481565b3480156103aa57600080fd5b50600354600160a01b900460ff165b604051901515815260200161021d565b3480156103d557600080fd5b506003546103b990600160a01b900460ff1681565b3480156103f657600080fd5b506000546001600160a01b0316610209565b34801561041457600080fd5b506101e76104233660046118a8565b610b60565b34801561043457600080fd5b5061027c600c5481565b34801561044a57600080fd5b506101e7610459366004611684565b610ca1565b34801561046a57600080fd5b5061027c600a5481565b34801561048057600080fd5b50600654610209906001600160a01b031681565b3480156104a057600080fd5b506103b96104af36600461171e565b600d6020526000908152604090205460ff1681565b3480156104d057600080fd5b506008546102c09061ffff1681565b3480156104eb57600080fd5b506101e76104fa36600461171e565b610d27565b34801561050b57600080fd5b5061027c600b5481565b34801561052157600080fd5b506101e7610530366004611684565b610d93565b34801561054157600080fd5b50600454610209906001600160a01b031681565b6005546001600160a01b03163314610580576040516327365a1960e01b815260040160405180910390fd5b61271061ffff821611156105a757604051630ef7893160e01b815260040160405180910390fd5b6008546040805161ffff928316815291831660208301527fa3548295fa266701fb2455011980392d0693eeff50c36c961fd1e6a8a8403429910160405180910390a16008805461ffff191661ffff92909216919091179055565b6004546001600160a01b0316331461062c57604051634755657960e01b815260040160405180910390fd5b600354600160a01b900460ff1661067f576040516306e0450760e31b815260206004820152601160248201527045706f636820696e2070726f677265737360781b60448201526064015b60405180910390fd5b60016009600082825461069291906119ad565b90915550506003805460ff60a01b191690556000600a556106b38282610e2e565b7f968139de8ea4f6dca3f75fdde04ee69529bde77210bb1cc0b58e954fd3d9b6196009546040516106e691815260200190565b60405180910390a15050565b6000546001600160a01b0316331461071c5760405162461bcd60e51b8152600401610676906119c5565b6004546040516001600160a01b038084169216907f39eb67354e1d981c44468f6a2b1837bb1598cf711fe761db800b185706b4e8cb90600090a3600480546001600160a01b0319166001600160a01b0392909216919091179055565b6002600154036107ca5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610676565b6002600155600354600160a01b900460ff16156107fa57604051637eed46cd60e11b815260040160405180910390fd5b60095460408051602080820193909352338183015260608082018790528251808303909101815260808201835280519084012060a0808301919091528251808303909101815260c0909101909152805191012061088e838380806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250506007549150849050610e63565b6108ab5760405163582f497d60e11b815260040160405180910390fd5b6000818152600d602052604090205460ff16156108db57604051632cfe303760e21b815260040160405180910390fd5b6000818152600d602052604090819020805460ff19166001179055600254905163a9059cbb60e01b8152336004820152602481018690526001600160a01b039091169063a9059cbb906044016020604051808303816000875af1158015610946573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061096a91906119fa565b50600954604080519182526020820186905233917f987d620f307ff6b94d58743cb7a7509f24071586a77759b77c2d4e29f75a2f9a910160405180910390a25050600180555050565b6000546001600160a01b031633146109dd5760405162461bcd60e51b8152600401610676906119c5565b600c5460408051918252602082018390527fb1526092a93c65fcdc17421d27e2e30fcb5aa9b40085e50be17a4b76c3c51c51910160405180910390a1600c55565b6000546001600160a01b03163314610a485760405162461bcd60e51b8152600401610676906119c5565b6006546040516001600160a01b038084169216907f430359a6d97ced2b6f93c77a91e7ce9dfd43252eb91e916adba170485cd8a6a490600090a3600680546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610ace5760405162461bcd60e51b8152600401610676906119c5565b6003546040516001600160a01b038084169216907f5c7887d1daf8d7fd266b3e3a75b86b49111acf8bee0cdf235a99c6727094b6ff90600090a3600380546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610b545760405162461bcd60e51b8152600401610676906119c5565b610b5e6000610e79565b565b6004546001600160a01b03163314610b8b57604051634755657960e01b815260040160405180910390fd5b6009548814610bad57604051630b8297d160e41b815260040160405180910390fd5b47871115610bd757604051635c4a8f5560e01b815260048101889052476024820152604401610676565b8351835181141580610bea575080835114155b80610bf6575080825114155b15610c1457604051632b477e7160e11b815260040160405180910390fd5b6003805460ff60a01b1916600160a01b179055600954604080519182524260208301527f27bd0cff633fd950c11ae24bd614aa2d87d938a50d6b65573c3743be7a831f57910160405180910390a16000881180610c72575060008551115b15610c8657610c8688888888888888610ec9565b600a5415610c9657610c96611120565b505050505050505050565b6000546001600160a01b03163314610ccb5760405162461bcd60e51b8152600401610676906119c5565b6005546040516001600160a01b038084169216907f75b7fe723ac984bff13d3b320ed1a920035692e4a8e56fb2457774e7535c0d1d90600090a3600580546001600160a01b0319166001600160a01b0392909216919091179055565b6005546001600160a01b03163314610d52576040516327365a1960e01b815260040160405180910390fd5b600b5460408051918252602082018390527fca0542093af2ac14ccf6e52b6e1a131c7e2825fb3b51139bf1dd8186a1339e95910160405180910390a1600b55565b6000546001600160a01b03163314610dbd5760405162461bcd60e51b8152600401610676906119c5565b6001600160a01b038116610e225760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610676565b610e2b81610e79565b50565b60078290556040517fcbf50fb43f807a45d3040d47fc400e73022e39ad9e71eb0e6ac30abbb11254c0906106e6908390611a1c565b600082610e7085846111e8565b14949350505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8615610eda57610eda87878761125c565b60008060005b865181101561111457868181518110610efb57610efb611a71565b60200260200101519250858181518110610f1757610f17611a71565b60209081029190910101516040516370a0823160e01b81523060048201529092506001600160a01b038416906370a0823190602401602060405180830381865afa158015610f69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f8d9190611a87565b821115611032576040516370a0823160e01b8152306004820152839083906001600160a01b038316906370a0823190602401602060405180830381865afa158015610fdc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110009190611a87565b60405163ebd6ced960e01b81526001600160a01b03909316600484015260248301919091526044820152606401610676565b6002546001600160a01b0390811690841603611057576110528383611385565b61110c565b60035460405163095ea7b360e01b81526001600160a01b039182166004820152602481018490529084169063095ea7b3906044016020604051808303816000875af11580156110aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ce91906119fa565b5061110c828583815181106110e5576110e5611a71565b60200260200101518784815181106110ff576110ff611a71565b60200260200101516113e6565b600101610ee0565b50505050505050505050565b600a8054600090915560025460065460405163a9059cbb60e01b81526001600160a01b0391821660048201526024810184905291169063a9059cbb906044016020604051808303816000875af115801561117e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111a291906119fa565b506006546040518281526001600160a01b03909116907f5ecd24bb88c90abaa45d5cf6e74b18932d53a1fff8a0363c054817c2081203dd9060200160405180910390a250565b600081815b845181101561125457600085828151811061120a5761120a611a71565b602002602001015190508083116112305760008381526020829052604090209250611241565b600081815260208490526040902092505b508061124c81611aa0565b9150506111ed565b509392505050565b600354600c546000916001600160a01b031690637ff36ab590869085908790309061128790426119ad565b6040518663ffffffff1660e01b81526004016112a69493929190611afd565b60006040518083038185885af11580156112c4573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f191682016040526112ed9190810190611b32565b905060006113148260018151811061130757611307611a71565b60200260200101516114be565b90507f8ba8eee785cd2af8020ee28bd97c37d9d1095205621500ed770d0d478c12db318260018151811061134a5761134a611a71565b602002602001015182600954604051611376939291909283526020830191909152604082015260600190565b60405180910390a15050505050565b6000611390826114be565b600954604080518581526020810184905280820192909252519192506001600160a01b038516917ff69f2787ff7a460f3aa50fad5651603571f99d2b1d2434ada34d5ad75d80ebf19181900360600190a2505050565b600354600c546000916001600160a01b0316906338ed173990869086908690309061141190426119ad565b6040518663ffffffff1660e01b8152600401611431959493929190611bc3565b6000604051808303816000875af1158015611450573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526114789190810190611b32565b90506114b88260008151811061149057611490611a71565b6020026020010151826001815181106114ab576114ab611a71565b6020026020010151611385565b50505050565b60085460009061ffff161561155357600854600090612710906114e690859061ffff16611bff565b6114f09190611c1e565b90506114fc8184611c40565b925080600a600082825461151091906119ad565b909155505060095460408051918252602082018390527f1afae4f1be5f3d468aa35441a60746d7ec521f2b69075214d296b20028707f78910160405180910390a1505b5090565b60006020828403121561156957600080fd5b813561ffff8116811461157b57600080fd5b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115c1576115c1611582565b604052919050565b600080604083850312156115dc57600080fd5b8235915060208084013567ffffffffffffffff808211156115fc57600080fd5b818601915086601f83011261161057600080fd5b81358181111561162257611622611582565b611634601f8201601f19168501611598565b9150808252878482850101111561164a57600080fd5b80848401858401376000848284010152508093505050509250929050565b80356001600160a01b038116811461167f57600080fd5b919050565b60006020828403121561169657600080fd5b61157b82611668565b6000806000604084860312156116b457600080fd5b83359250602084013567ffffffffffffffff808211156116d357600080fd5b818601915086601f8301126116e757600080fd5b8135818111156116f657600080fd5b8760208260051b850101111561170b57600080fd5b6020830194508093505050509250925092565b60006020828403121561173057600080fd5b5035919050565b600067ffffffffffffffff82111561175157611751611582565b5060051b60200190565b600082601f83011261176c57600080fd5b8135602061178161177c83611737565b611598565b82815260059290921b840181019181810190868411156117a057600080fd5b8286015b848110156117c2576117b581611668565b83529183019183016117a4565b509695505050505050565b600082601f8301126117de57600080fd5b813560206117ee61177c83611737565b82815260059290921b8401810191818101908684111561180d57600080fd5b8286015b848110156117c25780358352918301918301611811565b600082601f83011261183957600080fd5b8135602061184961177c83611737565b82815260059290921b8401810191818101908684111561186857600080fd5b8286015b848110156117c257803567ffffffffffffffff81111561188c5760008081fd5b61189a8986838b010161175b565b84525091830191830161186c565b600080600080600080600080610100898b0312156118c557600080fd5b8835975060208901359650604089013567ffffffffffffffff808211156118eb57600080fd5b6118f78c838d0161175b565b975060608b0135965060808b013591508082111561191457600080fd5b6119208c838d0161175b565b955060a08b013591508082111561193657600080fd5b6119428c838d016117cd565b945060c08b013591508082111561195857600080fd5b6119648c838d01611828565b935060e08b013591508082111561197a57600080fd5b506119878b828c016117cd565b9150509295985092959890939650565b634e487b7160e01b600052601160045260246000fd5b600082198211156119c0576119c0611997565b500190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b600060208284031215611a0c57600080fd5b8151801515811461157b57600080fd5b600060208083528351808285015260005b81811015611a4957858101830151858201604001528201611a2d565b81811115611a5b576000604083870101525b50601f01601f1916929092016040019392505050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a9957600080fd5b5051919050565b600060018201611ab257611ab2611997565b5060010190565b600081518084526020808501945080840160005b83811015611af25781516001600160a01b031687529582019590820190600101611acd565b509495945050505050565b848152608060208201526000611b166080830186611ab9565b6001600160a01b03949094166040830152506060015292915050565b60006020808385031215611b4557600080fd5b825167ffffffffffffffff811115611b5c57600080fd5b8301601f81018513611b6d57600080fd5b8051611b7b61177c82611737565b81815260059190911b82018301908381019087831115611b9a57600080fd5b928401925b82841015611bb857835182529284019290840190611b9f565b979650505050505050565b85815284602082015260a060408201526000611be260a0830186611ab9565b6001600160a01b0394909416606083015250608001529392505050565b6000816000190483118215151615611c1957611c19611997565b500290565b600082611c3b57634e487b7160e01b600052601260045260246000fd5b500490565b600082821015611c5257611c52611997565b50039056fea2646970667358221220ea1bf1d37cf509f05203e6885888458b046273604ae684c0d50fb5a7023182f264736f6c634300080e0033000000000000000000000000f7ffef737e122fdac725898201d41fd30df71d1a000000000000000000000000d6901cfba94ae408d6ccef593cda88914d775104000000000000000000000000a8047c2a86d5a188b0e15c3c10e2bc144cb272c2000000000000000000000000618679df9efcd19694bb1daa8d00718eacfa2883000000000000000000000000d9e1ce17f2641f24ae83637ab66a2cca9c378b9f

Deployed Bytecode

0x6080604052600436106101bb5760003560e01c80637983f13c116100ec578063c5f956af1161008a578063eb4af04511610064578063eb4af045146104df578063f1887684146104ff578063f2fde38b14610515578063fc6f94681461053557600080fd5b8063c5f956af14610474578063cc3c0f0614610494578063e80cfa5e146104c457600080fd5b806393821371116100c6578063938213711461040857806394de34f1146104285780639a3cac6a1461043e5780639a67430f1461045e57600080fd5b80637983f13c1461039e5780637d5a9b5c146103c95780638da5cb5b146103ea57600080fd5b8063430d8536116101595780636605bfda116101335780636605bfda146103335780636cc91bca14610353578063715018a614610373578063766718081461038857600080fd5b8063430d8536146102d35780634f72d846146102f357806355a373d61461031357600080fd5b80632c1e816d116101955780632c1e816d146102465780632eb4a7ab146102665780632f52ebb71461028a5780633eb6e846146102aa57600080fd5b806318dbf545146101c75780632131c68c146101e957806321405ba41461022657600080fd5b366101c257005b600080fd5b3480156101d357600080fd5b506101e76101e2366004611557565b610555565b005b3480156101f557600080fd5b50600554610209906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561023257600080fd5b506101e76102413660046115c9565b610601565b34801561025257600080fd5b506101e7610261366004611684565b6106f2565b34801561027257600080fd5b5061027c60075481565b60405190815260200161021d565b34801561029657600080fd5b506101e76102a536600461169f565b610778565b3480156102b657600080fd5b506102c061271081565b60405161ffff909116815260200161021d565b3480156102df57600080fd5b506101e76102ee36600461171e565b6109b3565b3480156102ff57600080fd5b50600354610209906001600160a01b031681565b34801561031f57600080fd5b50600254610209906001600160a01b031681565b34801561033f57600080fd5b506101e761034e366004611684565b610a1e565b34801561035f57600080fd5b506101e761036e366004611684565b610aa4565b34801561037f57600080fd5b506101e7610b2a565b34801561039457600080fd5b5061027c60095481565b3480156103aa57600080fd5b50600354600160a01b900460ff165b604051901515815260200161021d565b3480156103d557600080fd5b506003546103b990600160a01b900460ff1681565b3480156103f657600080fd5b506000546001600160a01b0316610209565b34801561041457600080fd5b506101e76104233660046118a8565b610b60565b34801561043457600080fd5b5061027c600c5481565b34801561044a57600080fd5b506101e7610459366004611684565b610ca1565b34801561046a57600080fd5b5061027c600a5481565b34801561048057600080fd5b50600654610209906001600160a01b031681565b3480156104a057600080fd5b506103b96104af36600461171e565b600d6020526000908152604090205460ff1681565b3480156104d057600080fd5b506008546102c09061ffff1681565b3480156104eb57600080fd5b506101e76104fa36600461171e565b610d27565b34801561050b57600080fd5b5061027c600b5481565b34801561052157600080fd5b506101e7610530366004611684565b610d93565b34801561054157600080fd5b50600454610209906001600160a01b031681565b6005546001600160a01b03163314610580576040516327365a1960e01b815260040160405180910390fd5b61271061ffff821611156105a757604051630ef7893160e01b815260040160405180910390fd5b6008546040805161ffff928316815291831660208301527fa3548295fa266701fb2455011980392d0693eeff50c36c961fd1e6a8a8403429910160405180910390a16008805461ffff191661ffff92909216919091179055565b6004546001600160a01b0316331461062c57604051634755657960e01b815260040160405180910390fd5b600354600160a01b900460ff1661067f576040516306e0450760e31b815260206004820152601160248201527045706f636820696e2070726f677265737360781b60448201526064015b60405180910390fd5b60016009600082825461069291906119ad565b90915550506003805460ff60a01b191690556000600a556106b38282610e2e565b7f968139de8ea4f6dca3f75fdde04ee69529bde77210bb1cc0b58e954fd3d9b6196009546040516106e691815260200190565b60405180910390a15050565b6000546001600160a01b0316331461071c5760405162461bcd60e51b8152600401610676906119c5565b6004546040516001600160a01b038084169216907f39eb67354e1d981c44468f6a2b1837bb1598cf711fe761db800b185706b4e8cb90600090a3600480546001600160a01b0319166001600160a01b0392909216919091179055565b6002600154036107ca5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610676565b6002600155600354600160a01b900460ff16156107fa57604051637eed46cd60e11b815260040160405180910390fd5b60095460408051602080820193909352338183015260608082018790528251808303909101815260808201835280519084012060a0808301919091528251808303909101815260c0909101909152805191012061088e838380806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250506007549150849050610e63565b6108ab5760405163582f497d60e11b815260040160405180910390fd5b6000818152600d602052604090205460ff16156108db57604051632cfe303760e21b815260040160405180910390fd5b6000818152600d602052604090819020805460ff19166001179055600254905163a9059cbb60e01b8152336004820152602481018690526001600160a01b039091169063a9059cbb906044016020604051808303816000875af1158015610946573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061096a91906119fa565b50600954604080519182526020820186905233917f987d620f307ff6b94d58743cb7a7509f24071586a77759b77c2d4e29f75a2f9a910160405180910390a25050600180555050565b6000546001600160a01b031633146109dd5760405162461bcd60e51b8152600401610676906119c5565b600c5460408051918252602082018390527fb1526092a93c65fcdc17421d27e2e30fcb5aa9b40085e50be17a4b76c3c51c51910160405180910390a1600c55565b6000546001600160a01b03163314610a485760405162461bcd60e51b8152600401610676906119c5565b6006546040516001600160a01b038084169216907f430359a6d97ced2b6f93c77a91e7ce9dfd43252eb91e916adba170485cd8a6a490600090a3600680546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610ace5760405162461bcd60e51b8152600401610676906119c5565b6003546040516001600160a01b038084169216907f5c7887d1daf8d7fd266b3e3a75b86b49111acf8bee0cdf235a99c6727094b6ff90600090a3600380546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610b545760405162461bcd60e51b8152600401610676906119c5565b610b5e6000610e79565b565b6004546001600160a01b03163314610b8b57604051634755657960e01b815260040160405180910390fd5b6009548814610bad57604051630b8297d160e41b815260040160405180910390fd5b47871115610bd757604051635c4a8f5560e01b815260048101889052476024820152604401610676565b8351835181141580610bea575080835114155b80610bf6575080825114155b15610c1457604051632b477e7160e11b815260040160405180910390fd5b6003805460ff60a01b1916600160a01b179055600954604080519182524260208301527f27bd0cff633fd950c11ae24bd614aa2d87d938a50d6b65573c3743be7a831f57910160405180910390a16000881180610c72575060008551115b15610c8657610c8688888888888888610ec9565b600a5415610c9657610c96611120565b505050505050505050565b6000546001600160a01b03163314610ccb5760405162461bcd60e51b8152600401610676906119c5565b6005546040516001600160a01b038084169216907f75b7fe723ac984bff13d3b320ed1a920035692e4a8e56fb2457774e7535c0d1d90600090a3600580546001600160a01b0319166001600160a01b0392909216919091179055565b6005546001600160a01b03163314610d52576040516327365a1960e01b815260040160405180910390fd5b600b5460408051918252602082018390527fca0542093af2ac14ccf6e52b6e1a131c7e2825fb3b51139bf1dd8186a1339e95910160405180910390a1600b55565b6000546001600160a01b03163314610dbd5760405162461bcd60e51b8152600401610676906119c5565b6001600160a01b038116610e225760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610676565b610e2b81610e79565b50565b60078290556040517fcbf50fb43f807a45d3040d47fc400e73022e39ad9e71eb0e6ac30abbb11254c0906106e6908390611a1c565b600082610e7085846111e8565b14949350505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8615610eda57610eda87878761125c565b60008060005b865181101561111457868181518110610efb57610efb611a71565b60200260200101519250858181518110610f1757610f17611a71565b60209081029190910101516040516370a0823160e01b81523060048201529092506001600160a01b038416906370a0823190602401602060405180830381865afa158015610f69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f8d9190611a87565b821115611032576040516370a0823160e01b8152306004820152839083906001600160a01b038316906370a0823190602401602060405180830381865afa158015610fdc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110009190611a87565b60405163ebd6ced960e01b81526001600160a01b03909316600484015260248301919091526044820152606401610676565b6002546001600160a01b0390811690841603611057576110528383611385565b61110c565b60035460405163095ea7b360e01b81526001600160a01b039182166004820152602481018490529084169063095ea7b3906044016020604051808303816000875af11580156110aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ce91906119fa565b5061110c828583815181106110e5576110e5611a71565b60200260200101518784815181106110ff576110ff611a71565b60200260200101516113e6565b600101610ee0565b50505050505050505050565b600a8054600090915560025460065460405163a9059cbb60e01b81526001600160a01b0391821660048201526024810184905291169063a9059cbb906044016020604051808303816000875af115801561117e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111a291906119fa565b506006546040518281526001600160a01b03909116907f5ecd24bb88c90abaa45d5cf6e74b18932d53a1fff8a0363c054817c2081203dd9060200160405180910390a250565b600081815b845181101561125457600085828151811061120a5761120a611a71565b602002602001015190508083116112305760008381526020829052604090209250611241565b600081815260208490526040902092505b508061124c81611aa0565b9150506111ed565b509392505050565b600354600c546000916001600160a01b031690637ff36ab590869085908790309061128790426119ad565b6040518663ffffffff1660e01b81526004016112a69493929190611afd565b60006040518083038185885af11580156112c4573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f191682016040526112ed9190810190611b32565b905060006113148260018151811061130757611307611a71565b60200260200101516114be565b90507f8ba8eee785cd2af8020ee28bd97c37d9d1095205621500ed770d0d478c12db318260018151811061134a5761134a611a71565b602002602001015182600954604051611376939291909283526020830191909152604082015260600190565b60405180910390a15050505050565b6000611390826114be565b600954604080518581526020810184905280820192909252519192506001600160a01b038516917ff69f2787ff7a460f3aa50fad5651603571f99d2b1d2434ada34d5ad75d80ebf19181900360600190a2505050565b600354600c546000916001600160a01b0316906338ed173990869086908690309061141190426119ad565b6040518663ffffffff1660e01b8152600401611431959493929190611bc3565b6000604051808303816000875af1158015611450573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526114789190810190611b32565b90506114b88260008151811061149057611490611a71565b6020026020010151826001815181106114ab576114ab611a71565b6020026020010151611385565b50505050565b60085460009061ffff161561155357600854600090612710906114e690859061ffff16611bff565b6114f09190611c1e565b90506114fc8184611c40565b925080600a600082825461151091906119ad565b909155505060095460408051918252602082018390527f1afae4f1be5f3d468aa35441a60746d7ec521f2b69075214d296b20028707f78910160405180910390a1505b5090565b60006020828403121561156957600080fd5b813561ffff8116811461157b57600080fd5b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115c1576115c1611582565b604052919050565b600080604083850312156115dc57600080fd5b8235915060208084013567ffffffffffffffff808211156115fc57600080fd5b818601915086601f83011261161057600080fd5b81358181111561162257611622611582565b611634601f8201601f19168501611598565b9150808252878482850101111561164a57600080fd5b80848401858401376000848284010152508093505050509250929050565b80356001600160a01b038116811461167f57600080fd5b919050565b60006020828403121561169657600080fd5b61157b82611668565b6000806000604084860312156116b457600080fd5b83359250602084013567ffffffffffffffff808211156116d357600080fd5b818601915086601f8301126116e757600080fd5b8135818111156116f657600080fd5b8760208260051b850101111561170b57600080fd5b6020830194508093505050509250925092565b60006020828403121561173057600080fd5b5035919050565b600067ffffffffffffffff82111561175157611751611582565b5060051b60200190565b600082601f83011261176c57600080fd5b8135602061178161177c83611737565b611598565b82815260059290921b840181019181810190868411156117a057600080fd5b8286015b848110156117c2576117b581611668565b83529183019183016117a4565b509695505050505050565b600082601f8301126117de57600080fd5b813560206117ee61177c83611737565b82815260059290921b8401810191818101908684111561180d57600080fd5b8286015b848110156117c25780358352918301918301611811565b600082601f83011261183957600080fd5b8135602061184961177c83611737565b82815260059290921b8401810191818101908684111561186857600080fd5b8286015b848110156117c257803567ffffffffffffffff81111561188c5760008081fd5b61189a8986838b010161175b565b84525091830191830161186c565b600080600080600080600080610100898b0312156118c557600080fd5b8835975060208901359650604089013567ffffffffffffffff808211156118eb57600080fd5b6118f78c838d0161175b565b975060608b0135965060808b013591508082111561191457600080fd5b6119208c838d0161175b565b955060a08b013591508082111561193657600080fd5b6119428c838d016117cd565b945060c08b013591508082111561195857600080fd5b6119648c838d01611828565b935060e08b013591508082111561197a57600080fd5b506119878b828c016117cd565b9150509295985092959890939650565b634e487b7160e01b600052601160045260246000fd5b600082198211156119c0576119c0611997565b500190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b600060208284031215611a0c57600080fd5b8151801515811461157b57600080fd5b600060208083528351808285015260005b81811015611a4957858101830151858201604001528201611a2d565b81811115611a5b576000604083870101525b50601f01601f1916929092016040019392505050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a9957600080fd5b5051919050565b600060018201611ab257611ab2611997565b5060010190565b600081518084526020808501945080840160005b83811015611af25781516001600160a01b031687529582019590820190600101611acd565b509495945050505050565b848152608060208201526000611b166080830186611ab9565b6001600160a01b03949094166040830152506060015292915050565b60006020808385031215611b4557600080fd5b825167ffffffffffffffff811115611b5c57600080fd5b8301601f81018513611b6d57600080fd5b8051611b7b61177c82611737565b81815260059190911b82018301908381019087831115611b9a57600080fd5b928401925b82841015611bb857835182529284019290840190611b9f565b979650505050505050565b85815284602082015260a060408201526000611be260a0830186611ab9565b6001600160a01b0394909416606083015250608001529392505050565b6000816000190483118215151615611c1957611c19611997565b500290565b600082611c3b57634e487b7160e01b600052601260045260246000fd5b500490565b600082821015611c5257611c52611997565b50039056fea2646970667358221220ea1bf1d37cf509f05203e6885888458b046273604ae684c0d50fb5a7023182f264736f6c634300080e0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000f7ffef737e122fdac725898201d41fd30df71d1a000000000000000000000000d6901cfba94ae408d6ccef593cda88914d775104000000000000000000000000a8047c2a86d5a188b0e15c3c10e2bc144cb272c2000000000000000000000000618679df9efcd19694bb1daa8d00718eacfa2883000000000000000000000000d9e1ce17f2641f24ae83637ab66a2cca9c378b9f

-----Decoded View---------------
Arg [0] : _adminAddress (address): 0xf7FFEF737E122FdaC725898201d41Fd30DF71d1a
Arg [1] : _treasuryAddress (address): 0xD6901CfbA94ae408D6cCef593CDa88914D775104
Arg [2] : _daoAddress (address): 0xa8047C2a86D5A188B0e15C3C10E2bc144cB272C2
Arg [3] : tokenAddress (address): 0x618679dF9EfCd19694BB1daa8D00718Eacfa2883
Arg [4] : routerAddress (address): 0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F

-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000f7ffef737e122fdac725898201d41fd30df71d1a
Arg [1] : 000000000000000000000000d6901cfba94ae408d6ccef593cda88914d775104
Arg [2] : 000000000000000000000000a8047c2a86d5a188b0e15c3c10e2bc144cb272c2
Arg [3] : 000000000000000000000000618679df9efcd19694bb1daa8d00718eacfa2883
Arg [4] : 000000000000000000000000d9e1ce17f2641f24ae83637ab66a2cca9c378b9f


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.