false
false
0

Contract Address Details

0xd7b8D88603De93dD9b430ea5f81dC32C117Df250

Contract Name
Distribution
Creator
0x4598a6–d10d29 at 0x70029a–bcbe85
Balance
0 FLR
Tokens
Fetching tokens...
Transactions
4,073 Transactions
Transfers
0 Transfers
Gas Used
7,342,608,495
Last Balance Update
23039551
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
Distribution




Optimization enabled
true
Compiler version
v0.7.6+commit.7338295f




Optimization runs
200
Verified at
2022-07-13T21:21:08.882375Z

Constructor Arguments

0000000000000000000000004598a6c05910ab914f0cbaaca1911cd337d10d2900000000000000000000000010000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000064602480

Arg [0] (address) : 0x4598a6c05910ab914f0cbaaca1911cd337d10d29
Arg [1] (address) : 0x1000000000000000000000000000000000000004
Arg [2] (uint256) : 1684022400

              

./contracts/tokenPools/implementation/Distribution.sol

// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;

import "../../governance/implementation/Governed.sol";
import "@openzeppelin/contracts/utils/SafeCast.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/math/Math.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "../../utils/implementation/SafePct.sol";
import "../../userInterfaces/IDistribution.sol";
import "../interface/IITokenPool.sol";

/**
 * @title Distribution
 * @notice A contract to manage the ongoing airdrop distribution after the initial airdrop allocation. 
 * The remaining amount is distributed by this contract, with a set rate every 30 days
 * @notice The balance that will be added to this contract must initially be a part of circulating supply 
 **/
contract Distribution is Governed, ReentrancyGuard, IDistribution, IITokenPool {
    using SafeCast for uint256;
    using SafeMath for uint256;
    using SafePct for uint256;

    // Airdrop Account stuct (for memory)
    struct AirdropAccount {
        uint256 entitlementBalanceWei;            // 100% of entitled airdrop in Wei
        uint256 totalClaimedWei;                  // already claimed Wei
        uint256 optOutBalanceWei;                 // The balance that accounts is opting out (per account)
        uint256 airdroppedAtGenesisWei;           // Amount airdropped (initial airdrop amount)
        // HealthChecks:
        // * entitlementBalanceWei >= totalClaimedWei 
        // * entitlementBalanceWei == totalClaimedWei + optOutBalanceWei if optOutBalanceWei > 0
        // * entitlementBalanceWei == totalClaimedWei at some point in the future
    }

    // constants
    uint256 internal constant MONTH = 30 days;
    uint256 internal constant MAX_ADDRESS_BATCH_SIZE = 1000;
    uint256 internal constant TOTAL_BIPS = 10000;
    uint256 internal constant CLAIMED_AT_GENESIS_BIPS = 1500;
    uint256 internal constant TOTAL_CLAIMABLE_BIPS = 8500;
    uint256 internal constant MONTHLY_CLAIMABLE_BIPS = 237;  // 2.37% every 30 days

    // storage
    uint256 public immutable latestEntitlementStartTs;  // Latest day 0 when contract starts
    mapping(address => AirdropAccount) public airdropAccounts;
    uint256 public totalEntitlementWei;   // Total wei to be distributed by this contract (all but initial airdrop)
    uint256 public totalClaimedWei;       // All wei already claimed
    uint256 public totalOptOutWei;        // The total opt-out Wei of all accounts that opt-out
    uint256 public withdrawnOptOutWei;    // Amount of opt-out Wei that was withdrawn by governance
    uint256 public entitlementStartTs;    // Day 0 when contract starts

    // contracts
    address public immutable treasury;

    // Errors
    string internal constant ERR_ADDRESS_ZERO = "address zero";
    string internal constant ERR_OUT_OF_BALANCE = "balance too low";
    string internal constant ERR_TOO_MANY = "too many";
    string internal constant ERR_NOT_REGISTERED = "not registered";
    string internal constant ERR_NOT_STARTED = "not started";
    string internal constant ERR_FULLY_CLAIMED = "already fully claimed";
    string internal constant ERR_OPT_OUT = "already opted out";
    string internal constant ERR_NO_BALANCE_CLAIMABLE = "no balance currently available";
    string internal constant ERR_ARRAY_MISMATCH = "arrays lengths mismatch";
    string internal constant ERR_ALREADY_STARTED = "already started";
    string internal constant ERR_TREASURY_ONLY = "treasury only";
    string internal constant ERR_IN_THE_PAST = "in the past";
    string internal constant ERR_WRONG_START_TIMESTAMP = "wrong start timestamp";

    /**
     * @dev This modifier ensures that this contract's balance matches the expected balance.
     */
    modifier mustBalance {
        _;
        require (_getExpectedBalance() <= address(this).balance, ERR_OUT_OF_BALANCE);
    }

    /**
     * @dev This modifier ensures that the entitelment was already started
     */
    modifier entitlementStarted {
        require (entitlementStartTs != 0 && entitlementStartTs < block.timestamp, ERR_NOT_STARTED);
        _;
    }

    /**
     * @dev Access control to protect methods to allow only minters to call select methods
     *   (like transferring balance out).
     */
    modifier accountCanClaim (address _owner) {
        require(airdropAccounts[_owner].airdroppedAtGenesisWei != 0, ERR_NOT_REGISTERED);
        require(airdropAccounts[_owner].optOutBalanceWei == 0, ERR_OPT_OUT);
        _;
    }

    constructor(
        address _governance,
        address _treasury,
        uint256 _latestEntitlementStartTs
    )
        Governed(_governance)
    {
        require(_treasury != address(0), ERR_ADDRESS_ZERO);
        require(_latestEntitlementStartTs >= block.timestamp, ERR_IN_THE_PAST);
        treasury = _treasury;
        latestEntitlementStartTs = _latestEntitlementStartTs;
    }

    /**
     * @notice Needed in order to receive funds from DistributionTreasury
     */
    receive() external payable {
        require(msg.sender == address(treasury), ERR_TREASURY_ONLY);
    }

    /**
     * @notice Method to set addresses and their respective balances in batches to this contract (airdrop)
     * @param toAddress array of adresses we are adding in batch
     * @param balance array of balances to be airdropped to respective accounts (total amount - 100%)
     * @dev Note that toAddress and balance arrays must be equal length
     * @dev Note that script must use the same batches to fill data (if restarted), otherwise duplicates may occure
     */
    function setAirdropBalances(address[] calldata toAddress, uint256[] calldata balance) external onlyGovernance {
        require(toAddress.length <= MAX_ADDRESS_BATCH_SIZE, ERR_TOO_MANY);
        require(toAddress.length == balance.length, ERR_ARRAY_MISMATCH);
        require (entitlementStartTs == 0, ERR_ALREADY_STARTED);

        if (airdropAccounts[toAddress[0]].entitlementBalanceWei > 0) return; // batch already added
        for (uint16 i = 0; i < toAddress.length; i++) {
            // Assume that when the initial 15% was allocated, that any remainder was truncated.
            // Therefore, compute the difference to obtain the remaining entitlement balance.
            uint256 claimedAtGenesis = balance[i].mulDiv(CLAIMED_AT_GENESIS_BIPS, TOTAL_BIPS);
            uint256 entiteledWei = balance[i].sub(claimedAtGenesis);
            airdropAccounts[toAddress[i]] =
                AirdropAccount({
                    entitlementBalanceWei: entiteledWei,
                    totalClaimedWei: 0,
                    optOutBalanceWei: 0,
                    airdroppedAtGenesisWei: claimedAtGenesis
                });
            totalEntitlementWei = totalEntitlementWei.add(entiteledWei);
        }
        // We added the accounts to airdrop, emit event
        emit AccountsAdded(toAddress);
    }

    /** 
     * @notice Start the distribution contract at _entitlementStartTs timestamp
     * @param _entitlementStartTs point in time when we start
     * @dev should be called immediately after all airdrop accounts and balances are set
     */
    function setEntitlementStart(uint256 _entitlementStartTs) external virtual onlyGovernance {
        require(entitlementStartTs == 0 || entitlementStartTs > block.timestamp, ERR_ALREADY_STARTED);
        require(_entitlementStartTs >= block.timestamp && _entitlementStartTs <= latestEntitlementStartTs,
            ERR_WRONG_START_TIMESTAMP);
        require(treasury.balance >= totalEntitlementWei || address(this).balance >= totalEntitlementWei,
            ERR_OUT_OF_BALANCE);
        entitlementStartTs = _entitlementStartTs;
        emit EntitlementStart(_entitlementStartTs);
    }

    /**
     * @notice Method to opt-out of receiving airdrop rewards
     * @dev 
     */
    function optOutOfAirdrop() external override accountCanClaim(msg.sender) entitlementStarted {
        // you can only opt-out for your address
        AirdropAccount storage airdropAccount = airdropAccounts[msg.sender];
        require(airdropAccount.entitlementBalanceWei > airdropAccount.totalClaimedWei, ERR_FULLY_CLAIMED);
        // emit opt-out event
        emit AccountOptOut(msg.sender);
        // set all unclaimed wei to opt-out balance
        airdropAccount.optOutBalanceWei = airdropAccount.entitlementBalanceWei - airdropAccount.totalClaimedWei;
        // Add this accounts opt-out balance to full opt-out balance
        totalOptOutWei = totalOptOutWei.add(airdropAccount.optOutBalanceWei);
    }

    /**
     * @notice Method for claiming unlocked airdrop amounts
     * @return _amountWei claimed wei
     */
    function claim(address payable _recipient) external override 
        entitlementStarted mustBalance nonReentrant accountCanClaim(msg.sender) 
        returns(uint256 _amountWei) 
    {
        // Get the account
        AirdropAccount storage airdropAccount = airdropAccounts[msg.sender];
        // Get the current claimable amount for the account
        _amountWei = _getCurrentClaimableWei(msg.sender);
        // Make sure we are not withdrawing 0 funds
        require(_amountWei > 0, ERR_NO_BALANCE_CLAIMABLE);
        // Update claimed balance
        airdropAccount.totalClaimedWei += _amountWei;
        // Update grand total claimed
        totalClaimedWei = totalClaimedWei.add(_amountWei);
        // Emit the claim event
        emit AccountClaimed(msg.sender);
        // Send
        /* solhint-disable avoid-low-level-calls */
        //slither-disable-next-line arbitrary-send   
        (bool success, ) = _recipient.call{value: _amountWei}("");
        /* solhint-enable avoid-low-level-calls */
        require(success, "error");
    }

    /**
     * @notice Method for withdrawing funds that were opt-out by users. Only accessible form governance address
     * @return _amountWei withdrawn opt-out wei
     * @param _targetAddress an address to withdraw funds to
     */
    function withdrawOptOutWei(address payable _targetAddress) external onlyGovernance entitlementStarted mustBalance 
        returns(uint256 _amountWei) 
    {
        require(totalOptOutWei > 0, ERR_NO_BALANCE_CLAIMABLE);
        require(totalOptOutWei != withdrawnOptOutWei, ERR_NO_BALANCE_CLAIMABLE);
        // Update opt-out balance
        _amountWei = totalOptOutWei.sub(withdrawnOptOutWei);
        withdrawnOptOutWei = totalOptOutWei;
        // emit the event
        emit OptOutWeiWithdrawn();
        // Send Wei to address
        _targetAddress.transfer(_amountWei);
    }

    function getTokenPoolSupplyData() external override view 
        returns (uint256 _lockedFundsWei, uint256 _totalInflationAuthorizedWei, uint256 _totalClaimedWei)
    {
        // This is the total amount of tokens that are actually already in circulating supply
        _lockedFundsWei = totalEntitlementWei;
        // We will never increase this balance since distribution funds are taken from genesis 
        /// amounts and not from inflation.
        _totalInflationAuthorizedWei = 0;
        // What was actually already added to circulating supply
        _totalClaimedWei = totalClaimedWei + withdrawnOptOutWei;
    }

    /**
     * @notice current claimable amount of wei for requesting account
     * @return _amountWei amount of wei available for this account at current time
     */
    function getClaimableAmount() external view override entitlementStarted 
        returns(uint256 _amountWei) 
    {
        _amountWei = _getCurrentClaimableWei(msg.sender);
    }

    /**
     * @notice current claimable amount of wei for account
     * @param account the address of an account we want to get the available wei
     * @return _amountWei amount of wei available for provided account at current time
     */
    function getClaimableAmountOf(address account) external view override entitlementStarted 
        returns(uint256 _amountWei) 
    {
        _amountWei = _getCurrentClaimableWei(account);
    }

    /**
     * @notice Time till next Wei will be claimable (in secods)
     * @return timeTill (sec) Time till next claimable Wei in seconds
     */
    function secondsTillNextClaim() external view override entitlementStarted 
        returns(uint256 timeTill) 
    {
        timeTill = _timeTillNextClaim(msg.sender);
    }

    /**
     * @notice Get the claimable percent for the current timestamp
     * @dev Every 30 days from initial day 2.37% of the total amount is unlocked and becomes available for claiming
     * @return percentBips maximal claimable bips at given time
     */
    function _getCurrentClaimablePercent() internal view entitlementStarted 
        returns(uint256 percentBips)
    {
        uint256 diffDays = block.timestamp.sub(entitlementStartTs).div(1 days);
        percentBips = Math.min(diffDays.div(30).mul(MONTHLY_CLAIMABLE_BIPS),TOTAL_CLAIMABLE_BIPS);
    }

    /**
     * @notice Get current claimable amount for users account
     * @dev Every 30 days from initial day 2.37% of the reward is released
     */
    function _getCurrentClaimableWei(address _owner) internal view entitlementStarted accountCanClaim(_owner) 
        returns(uint256 claimableWei)
    {
        // Attempt to get the account in question
        AirdropAccount memory airdropAccount = airdropAccounts[_owner];
        uint256 currentMaxClaimableBips = _getCurrentClaimablePercent();
        uint256 tempCla=airdropAccount.entitlementBalanceWei.mulDiv(currentMaxClaimableBips,TOTAL_CLAIMABLE_BIPS);
        // Can never claime more that we are initially entiteled to
        tempCla = Math.min(tempCla, airdropAccount.entitlementBalanceWei).toUint128();
        // Substract already claimed
        claimableWei = tempCla - airdropAccount.totalClaimedWei; 
    }

    /**
     * @notice Calculate the time till nex entitelment Wei is released  
     */
    function _timeTillNextClaim(address _account) internal view entitlementStarted accountCanClaim(_account) 
        returns(uint256 timeTill) 
    {
        // Get the account we want to check
        require(block.timestamp.sub(entitlementStartTs).div(MONTH) < 36, ERR_FULLY_CLAIMED);
        timeTill = MONTH.sub(block.timestamp.sub(entitlementStartTs).mod(MONTH));
    }

    /**
     * @notice Compute the expected balance of this contract.
     * @param _balanceExpectedWei   The computed balance expected.
     */
    function _getExpectedBalance() private view returns(uint256 _balanceExpectedWei) {
        return totalEntitlementWei.sub(totalClaimedWei).sub(withdrawnOptOutWei);
    }
}
        

./contracts/governance/implementation/Governed.sol

// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;

import { GovernedBase } from "./GovernedBase.sol";


/**
 * @title Governed
 * @dev For deployed, governed contracts, enforce a non-zero address at create time.
 **/
contract Governed is GovernedBase {
    constructor(address _governance) GovernedBase(_governance) {
        require(_governance != address(0), "_governance zero");
    }
}
          

./contracts/governance/implementation/GovernedBase.sol

// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;

import "../../userInterfaces/IGovernanceSettings.sol";


/**
 * @title Governed Base
 * @notice This abstract base class defines behaviors for a governed contract.
 * @dev This class is abstract so that specific behaviors can be defined for the constructor.
 *   Contracts should not be left ungoverned, but not all contract will have a constructor
 *   (for example those pre-defined in genesis).
 **/
abstract contract GovernedBase {
    struct TimelockedCall {
        uint256 allowedAfterTimestamp;
        bytes encodedCall;
    }
    
    // solhint-disable-next-line const-name-snakecase
    IGovernanceSettings public constant governanceSettings = 
        IGovernanceSettings(0x1000000000000000000000000000000000000007);

    address private initialGovernance;

    bool private initialised;
    
    bool public productionMode;
    
    bool private executing;
    
    mapping(bytes4 => TimelockedCall) public timelockedCalls;
    
    event GovernanceCallTimelocked(bytes4 selector, uint256 allowedAfterTimestamp, bytes encodedCall);
    event TimelockedGovernanceCallExecuted(bytes4 selector, uint256 timestamp);
    event TimelockedGovernanceCallCanceled(bytes4 selector, uint256 timestamp);
    
    event GovernanceInitialised(address initialGovernance);
    event GovernedProductionModeEntered(address governanceSettings);
    
    modifier onlyGovernance {
        if (executing || !productionMode) {
            _beforeExecute();
            _;
        } else {
            _recordTimelockedCall(msg.data);
        }
    }
    
    modifier onlyImmediateGovernance () {
        _checkOnlyGovernance();
        _;
    }

    constructor(address _initialGovernance) {
        if (_initialGovernance != address(0)) {
            initialise(_initialGovernance);
        }
    }

    /**
     * @notice Execute the timelocked governance calls once the timelock period expires.
     * @dev Only executor can call this method.
     * @param _selector The method selector (only one timelocked call per method is stored).
     */
    function executeGovernanceCall(bytes4 _selector) external {
        require(governanceSettings.isExecutor(msg.sender), "only executor");
        TimelockedCall storage call = timelockedCalls[_selector];
        require(call.allowedAfterTimestamp != 0, "timelock: invalid selector");
        require(block.timestamp >= call.allowedAfterTimestamp, "timelock: not allowed yet");
        bytes memory encodedCall = call.encodedCall;
        delete timelockedCalls[_selector];
        executing = true;
        //solhint-disable-next-line avoid-low-level-calls
        (bool success,) = address(this).call(encodedCall);
        executing = false;
        emit TimelockedGovernanceCallExecuted(_selector, block.timestamp);
        _passReturnOrRevert(success);
    }
    
    /**
     * Cancel a timelocked governance call before it has been executed.
     * @dev Only governance can call this method.
     * @param _selector The method selector.
     */
    function cancelGovernanceCall(bytes4 _selector) external onlyImmediateGovernance {
        require(timelockedCalls[_selector].allowedAfterTimestamp != 0, "timelock: invalid selector");
        emit TimelockedGovernanceCallCanceled(_selector, block.timestamp);
        delete timelockedCalls[_selector];
    }
    
    /**
     * Enter the production mode after all the initial governance settings have been set.
     * This enables timelocks and the governance is afterwards obtained by calling 
     * governanceSettings.getGovernanceAddress(). 
     */
    function switchToProductionMode() external {
        _checkOnlyGovernance();
        require(!productionMode, "already in production mode");
        initialGovernance = address(0);
        productionMode = true;
        emit GovernedProductionModeEntered(address(governanceSettings));
    }

    /**
     * @notice Initialize the governance address if not first initialized.
     */
    function initialise(address _initialGovernance) public virtual {
        require(initialised == false, "initialised != false");
        initialised = true;
        initialGovernance = _initialGovernance;
        emit GovernanceInitialised(_initialGovernance);
    }
    
    /**
     * Returns the current effective governance address.
     */
    function governance() public view returns (address) {
        return productionMode ? governanceSettings.getGovernanceAddress() : initialGovernance;
    }

    function _beforeExecute() private {
        if (executing) {
            // can only be run from executeGovernanceCall(), where we check that only executor can call
            // make sure nothing else gets executed, even in case of reentrancy
            assert(msg.sender == address(this));
            executing = false;
        } else {
            // must be called with: productionMode=false
            // must check governance in this case
            _checkOnlyGovernance();
        }
    }

    function _recordTimelockedCall(bytes calldata _data) private {
        _checkOnlyGovernance();
        bytes4 selector;
        //solhint-disable-next-line no-inline-assembly
        assembly {
            selector := calldataload(_data.offset)
        }
        uint256 timelock = governanceSettings.getTimelock();
        uint256 allowedAt = block.timestamp + timelock;
        timelockedCalls[selector] = TimelockedCall({
            allowedAfterTimestamp: allowedAt,
            encodedCall: _data
        });
        emit GovernanceCallTimelocked(selector, allowedAt, _data);
    }
    
    function _checkOnlyGovernance() private view {
        require(msg.sender == governance(), "only governance");
    }
    
    function _passReturnOrRevert(bool _success) private pure {
        // pass exact return or revert data - needs to be done in assembly
        //solhint-disable-next-line no-inline-assembly
        assembly {
            let size := returndatasize()
            let ptr := mload(0x40)
            mstore(0x40, add(ptr, size))
            returndatacopy(ptr, 0, size)
            if _success {
                return(ptr, size)
            }
            revert(ptr, size)
        }
    }
}
          

./contracts/tokenPools/interface/IITokenPool.sol

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.6 <0.9;

interface IITokenPool {

    /**
     * @notice Return token pool supply data
     * @return _lockedFundsWei                  Funds that are intentionally locked in the token pool 
     * and not part of circulating supply
     * @return _totalInflationAuthorizedWei     Total inflation authorized amount (wei)
     * @return _totalClaimedWei                 Total claimed amount (wei)
     */
    function getTokenPoolSupplyData() external returns (
        uint256 _lockedFundsWei,
        uint256 _totalInflationAuthorizedWei,
        uint256 _totalClaimedWei
    );
}
          

./contracts/userInterfaces/IDistribution.sol

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.6 <0.9;
pragma abicoder v2;

interface IDistribution {
    // Events
    event EntitlementStart(uint256 entitlementStartTs);
    event AccountClaimed(address indexed theAccount);
    event AccountOptOut(address indexed theAccount);
    event OptOutWeiWithdrawn();
    event AccountsAdded(address[] accountsArray);

    // Methods
    function claim(address payable _recipient) external returns(uint256 _amountWei);
    function optOutOfAirdrop() external;
    function getClaimableAmount() external view returns(uint256 _amountWei);
    function getClaimableAmountOf(address account) external view returns(uint256 _amountWei);
    function secondsTillNextClaim() external view returns(uint256 timetill);
}
          

./contracts/userInterfaces/IGovernanceSettings.sol

// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;


/**
 * A special contract that holds Flare governance address.
 * This contract enables updating governance address and timelock only by hard forking the network,
 * meaning only by updating validator code.
 */
interface IGovernanceSettings {
    /**
     * Get the governance account address.
     * The governance address can only be changed by a hardfork.
     */
    function getGovernanceAddress() external view returns (address);
    
    /**
     * Get the time in seconds that must pass between a governance call and execution.
     * The timelock value can only be changed by a hardfork.
     */
    function getTimelock() external view returns (uint256);
    
    /**
     * Get the addresses of the accounts that are allowed to execute the timelocked governance calls
     * once the timelock period expires.
     * Executors can be changed without a hardfork, via a normal governance call.
     */
    function getExecutors() external view returns (address[] memory);
    
    /**
     * Check whether an address is one of the executors.
     */
    function isExecutor(address _address) external view returns (bool);
}
          

./contracts/utils/implementation/SafePct.sol

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
import {SafeMath} from "@openzeppelin/contracts/math/SafeMath.sol";

/**
 * @dev Compute percentages safely without phantom overflows.
 *
 * Intermediate operations can overflow even when the result will always
 * fit into computed type. Developers usually
 * assume that overflows raise errors. `SafePct` restores this intuition by
 * reverting the transaction when such an operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 *
 * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
 * all math on `uint256` and `int256` and then downcasting.
 */
library SafePct {
    using SafeMath for uint256;
    /**
     * Requirements:
     *
     * - intermediate operations must revert on overflow
     */
    function mulDiv(uint256 x, uint256 y, uint256 z) internal pure returns (uint256) {
        require(z > 0, "Division by zero");

        if (x == 0) return 0;
        uint256 xy = x * y;
        if (xy / x == y) { // no overflow happened - same as in SafeMath mul
            return xy / z;
        }

        //slither-disable-next-line divide-before-multiply
        uint256 a = x / z;
        uint256 b = x % z; // x = a * z + b

        //slither-disable-next-line divide-before-multiply
        uint256 c = y / z;
        uint256 d = y % z; // y = c * z + d

        return (a.mul(c).mul(z)).add(a.mul(d)).add(b.mul(c)).add(b.mul(d).div(z));
    }
}
          

@openzeppelin/contracts/math/Math.sol

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    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);
    }
}
          

@openzeppelin/contracts/math/SafeMath.sol

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        uint256 c = a + b;
        if (c < a) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b > a) return (false, 0);
        return (true, a - b);
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) return (true, 0);
        uint256 c = a * b;
        if (c / a != b) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a / b);
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a % b);
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");
        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    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;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: division by zero");
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: modulo by zero");
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        return a - b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryDiv}.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a % b;
    }
}
          

@openzeppelin/contracts/utils/ReentrancyGuard.sol

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <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 () internal {
        _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 make 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;
    }
}
          

@openzeppelin/contracts/utils/SafeCast.sol

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;


/**
 * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
 * easily result in undesired exploitation or bugs, since developers usually
 * assume that overflows raise errors. `SafeCast` restores this intuition by
 * reverting the transaction when such an operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 *
 * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
 * all math on `uint256` and `int256` and then downcasting.
 */
library SafeCast {

    /**
     * @dev Returns the downcasted uint128 from uint256, reverting on
     * overflow (when the input is greater than largest uint128).
     *
     * Counterpart to Solidity's `uint128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        require(value < 2**128, "SafeCast: value doesn\'t fit in 128 bits");
        return uint128(value);
    }

    /**
     * @dev Returns the downcasted uint64 from uint256, reverting on
     * overflow (when the input is greater than largest uint64).
     *
     * Counterpart to Solidity's `uint64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     */
    function toUint64(uint256 value) internal pure returns (uint64) {
        require(value < 2**64, "SafeCast: value doesn\'t fit in 64 bits");
        return uint64(value);
    }

    /**
     * @dev Returns the downcasted uint32 from uint256, reverting on
     * overflow (when the input is greater than largest uint32).
     *
     * Counterpart to Solidity's `uint32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     */
    function toUint32(uint256 value) internal pure returns (uint32) {
        require(value < 2**32, "SafeCast: value doesn\'t fit in 32 bits");
        return uint32(value);
    }

    /**
     * @dev Returns the downcasted uint16 from uint256, reverting on
     * overflow (when the input is greater than largest uint16).
     *
     * Counterpart to Solidity's `uint16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     */
    function toUint16(uint256 value) internal pure returns (uint16) {
        require(value < 2**16, "SafeCast: value doesn\'t fit in 16 bits");
        return uint16(value);
    }

    /**
     * @dev Returns the downcasted uint8 from uint256, reverting on
     * overflow (when the input is greater than largest uint8).
     *
     * Counterpart to Solidity's `uint8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits.
     */
    function toUint8(uint256 value) internal pure returns (uint8) {
        require(value < 2**8, "SafeCast: value doesn\'t fit in 8 bits");
        return uint8(value);
    }

    /**
     * @dev Converts a signed int256 into an unsigned uint256.
     *
     * Requirements:
     *
     * - input must be greater than or equal to 0.
     */
    function toUint256(int256 value) internal pure returns (uint256) {
        require(value >= 0, "SafeCast: value must be positive");
        return uint256(value);
    }

    /**
     * @dev Returns the downcasted int128 from int256, reverting on
     * overflow (when the input is less than smallest int128 or
     * greater than largest int128).
     *
     * Counterpart to Solidity's `int128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     *
     * _Available since v3.1._
     */
    function toInt128(int256 value) internal pure returns (int128) {
        require(value >= -2**127 && value < 2**127, "SafeCast: value doesn\'t fit in 128 bits");
        return int128(value);
    }

    /**
     * @dev Returns the downcasted int64 from int256, reverting on
     * overflow (when the input is less than smallest int64 or
     * greater than largest int64).
     *
     * Counterpart to Solidity's `int64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     *
     * _Available since v3.1._
     */
    function toInt64(int256 value) internal pure returns (int64) {
        require(value >= -2**63 && value < 2**63, "SafeCast: value doesn\'t fit in 64 bits");
        return int64(value);
    }

    /**
     * @dev Returns the downcasted int32 from int256, reverting on
     * overflow (when the input is less than smallest int32 or
     * greater than largest int32).
     *
     * Counterpart to Solidity's `int32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     *
     * _Available since v3.1._
     */
    function toInt32(int256 value) internal pure returns (int32) {
        require(value >= -2**31 && value < 2**31, "SafeCast: value doesn\'t fit in 32 bits");
        return int32(value);
    }

    /**
     * @dev Returns the downcasted int16 from int256, reverting on
     * overflow (when the input is less than smallest int16 or
     * greater than largest int16).
     *
     * Counterpart to Solidity's `int16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     *
     * _Available since v3.1._
     */
    function toInt16(int256 value) internal pure returns (int16) {
        require(value >= -2**15 && value < 2**15, "SafeCast: value doesn\'t fit in 16 bits");
        return int16(value);
    }

    /**
     * @dev Returns the downcasted int8 from int256, reverting on
     * overflow (when the input is less than smallest int8 or
     * greater than largest int8).
     *
     * Counterpart to Solidity's `int8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits.
     *
     * _Available since v3.1._
     */
    function toInt8(int256 value) internal pure returns (int8) {
        require(value >= -2**7 && value < 2**7, "SafeCast: value doesn\'t fit in 8 bits");
        return int8(value);
    }

    /**
     * @dev Converts an unsigned uint256 into a signed int256.
     *
     * Requirements:
     *
     * - input must be less than or equal to maxInt256.
     */
    function toInt256(uint256 value) internal pure returns (int256) {
        require(value < 2**255, "SafeCast: value doesn't fit in an int256");
        return int256(value);
    }
}
          

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_governance","internalType":"address"},{"type":"address","name":"_treasury","internalType":"address"},{"type":"uint256","name":"_latestEntitlementStartTs","internalType":"uint256"}]},{"type":"event","name":"AccountClaimed","inputs":[{"type":"address","name":"theAccount","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"AccountOptOut","inputs":[{"type":"address","name":"theAccount","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"AccountsAdded","inputs":[{"type":"address[]","name":"accountsArray","internalType":"address[]","indexed":false}],"anonymous":false},{"type":"event","name":"EntitlementStart","inputs":[{"type":"uint256","name":"entitlementStartTs","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"GovernanceCallTimelocked","inputs":[{"type":"bytes4","name":"selector","internalType":"bytes4","indexed":false},{"type":"uint256","name":"allowedAfterTimestamp","internalType":"uint256","indexed":false},{"type":"bytes","name":"encodedCall","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"GovernanceInitialised","inputs":[{"type":"address","name":"initialGovernance","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"GovernedProductionModeEntered","inputs":[{"type":"address","name":"governanceSettings","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"OptOutWeiWithdrawn","inputs":[],"anonymous":false},{"type":"event","name":"TimelockedGovernanceCallCanceled","inputs":[{"type":"bytes4","name":"selector","internalType":"bytes4","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TimelockedGovernanceCallExecuted","inputs":[{"type":"bytes4","name":"selector","internalType":"bytes4","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"entitlementBalanceWei","internalType":"uint256"},{"type":"uint256","name":"totalClaimedWei","internalType":"uint256"},{"type":"uint256","name":"optOutBalanceWei","internalType":"uint256"},{"type":"uint256","name":"airdroppedAtGenesisWei","internalType":"uint256"}],"name":"airdropAccounts","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"cancelGovernanceCall","inputs":[{"type":"bytes4","name":"_selector","internalType":"bytes4"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"_amountWei","internalType":"uint256"}],"name":"claim","inputs":[{"type":"address","name":"_recipient","internalType":"address payable"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"entitlementStartTs","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"executeGovernanceCall","inputs":[{"type":"bytes4","name":"_selector","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"_amountWei","internalType":"uint256"}],"name":"getClaimableAmount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"_amountWei","internalType":"uint256"}],"name":"getClaimableAmountOf","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"_lockedFundsWei","internalType":"uint256"},{"type":"uint256","name":"_totalInflationAuthorizedWei","internalType":"uint256"},{"type":"uint256","name":"_totalClaimedWei","internalType":"uint256"}],"name":"getTokenPoolSupplyData","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"governance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IGovernanceSettings"}],"name":"governanceSettings","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialise","inputs":[{"type":"address","name":"_initialGovernance","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"latestEntitlementStartTs","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"optOutOfAirdrop","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"productionMode","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"timeTill","internalType":"uint256"}],"name":"secondsTillNextClaim","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setAirdropBalances","inputs":[{"type":"address[]","name":"toAddress","internalType":"address[]"},{"type":"uint256[]","name":"balance","internalType":"uint256[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setEntitlementStart","inputs":[{"type":"uint256","name":"_entitlementStartTs","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"switchToProductionMode","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"allowedAfterTimestamp","internalType":"uint256"},{"type":"bytes","name":"encodedCall","internalType":"bytes"}],"name":"timelockedCalls","inputs":[{"type":"bytes4","name":"","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalClaimedWei","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalEntitlementWei","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalOptOutWei","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"treasury","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"_amountWei","internalType":"uint256"}],"name":"withdrawOptOutWei","inputs":[{"type":"address","name":"_targetAddress","internalType":"address payable"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"withdrawnOptOutWei","inputs":[]},{"type":"receive","stateMutability":"payable"}]
              

Contract Creation Code

0x60c06040523480156200001157600080fd5b5060405162002f5838038062002f58833981810160405260608110156200003757600080fd5b508051602082015160409092015190919082806001600160a01b038116156200006557620000658162000207565b506001600160a01b038116620000b5576040805162461bcd60e51b815260206004820152601060248201526f5f676f7665726e616e6365207a65726f60801b604482015290519081900360640190fd5b50600160025560408051808201909152600c81526b61646472657373207a65726f60a01b60208201526001600160a01b038316620001745760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015620001385781810151838201526020016200011e565b50505050905090810190601f168015620001665780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060408051808201909152600b81526a1a5b881d1a19481c185cdd60aa1b602082015242821015620001e95760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315620001385781810151838201526020016200011e565b5060609190911b6001600160601b03191660a05260805250620002ca565b600054600160a01b900460ff161562000267576040805162461bcd60e51b815260206004820152601460248201527f696e697469616c6973656420213d2066616c7365000000000000000000000000604482015290519081900360640190fd5b60008054600160a01b60ff60a01b19909116176001600160a01b0319166001600160a01b03831690811790915560408051918252517f9789733827840833afc031fb2ef9ab6894271f77bad2085687cf4ae5c7bee4db916020908290030190a150565b60805160a05160601c612c58620003006000398061019d52806113555280611b615250806116675280611abe5250612c586000f3fe6080604052600436106101695760003560e01c806374e6310e116100d1578063c354bd6e1161008a578063e60eb6ff11610064578063e60eb6ff146106d0578063f2325e38146106e5578063f2a1f767146106fa578063f5a983831461070f57610249565b8063c354bd6e14610668578063e17f212e1461067d578063e28ef1f7146106a657610249565b806374e6310e146104f25780637fd45d2b146105a55780639d6a890f146105d85780639f71043e1461060b578063ae67716114610620578063b5551ab71461063557610249565b80635aa6e675116101235780635aa6e6751461035e5780635ff270791461038f57806361235585146103c557806361d027b31461049457806362354e03146104a957806367fc4029146104be57610249565b80626a1d511461024e5780631e83409a146102755780632dafdbbf146102a857806344a8ace2146102db57806344d94b4b146103345780634bb5696a1461034957610249565b366102495760408051808201909152600d81526c7472656173757279206f6e6c7960981b6020820152336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146102465760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561020b5781810151838201526020016101f3565b50505050905090810190601f1680156102385780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50005b600080fd5b34801561025a57600080fd5b50610263610724565b60408051918252519081900360200190f35b34801561028157600080fd5b506102636004803603602081101561029857600080fd5b50356001600160a01b031661072a565b3480156102b457600080fd5b506102bd610b2b565b60408051938452602084019290925282820152519081900360600190f35b3480156102e757600080fd5b5061030e600480360360208110156102fe57600080fd5b50356001600160a01b0316610b3f565b604080519485526020850193909352838301919091526060830152519081900360800190f35b34801561034057600080fd5b50610263610b68565b34801561035557600080fd5b50610263610b6e565b34801561036a57600080fd5b50610373610c03565b604080516001600160a01b039092168252519081900360200190f35b34801561039b57600080fd5b506103c3600480360360208110156103b257600080fd5b50356001600160e01b031916610c97565b005b3480156103d157600080fd5b506103c3600480360360408110156103e857600080fd5b81019060208101813564010000000081111561040357600080fd5b82018360208201111561041557600080fd5b8035906020019184602083028401116401000000008311171561043757600080fd5b91939092909160208101903564010000000081111561045557600080fd5b82018360208201111561046757600080fd5b8035906020019184602083028401116401000000008311171561048957600080fd5b509092509050610fec565b3480156104a057600080fd5b50610373611353565b3480156104b557600080fd5b50610373611377565b3480156104ca57600080fd5b506103c3600480360360208110156104e157600080fd5b50356001600160e01b031916611382565b3480156104fe57600080fd5b506105266004803603602081101561051557600080fd5b50356001600160e01b03191661146a565b6040518083815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610569578181015183820152602001610551565b50505050905090810190601f1680156105965780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b3480156105b157600080fd5b50610263600480360360208110156105c857600080fd5b50356001600160a01b0316611510565b3480156105e457600080fd5b506103c3600480360360208110156105fb57600080fd5b50356001600160a01b03166115a6565b34801561061757600080fd5b5061026361165f565b34801561062c57600080fd5b50610263611665565b34801561064157600080fd5b506102636004803603602081101561065857600080fd5b50356001600160a01b0316611689565b34801561067457600080fd5b5061026361195d565b34801561068957600080fd5b506106926119ed565b604080519115158252519081900360200190f35b3480156106b257600080fd5b506103c3600480360360208110156106c957600080fd5b50356119fd565b3480156106dc57600080fd5b50610263611c59565b3480156106f157600080fd5b50610263611c5f565b34801561070657600080fd5b506103c3611c65565b34801561071b57600080fd5b506103c3611ee8565b60075481565b6000600854600014158015610740575042600854105b6040518060400160405280600b81526020016a1b9bdd081cdd185c9d195960aa1b815250906107b05760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b50600280541415610808576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002805533600081815260036020818152604092839020909101548251808401909352600e83526d1b9bdd081c9959da5cdd195c995960921b918301919091526108935760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b506001600160a01b0381166000908152600360209081526040918290206002015482518084019093526011835270185b1c9958591e481bdc1d1959081bdd5d607a1b91830191909152156109285760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b503360008181526003602052604090209061094290611fa2565b9250600083116040518060400160405280601e81526020017f6e6f2062616c616e63652063757272656e746c7920617661696c61626c650000815250906109ca5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b50600181018054840190556005546109e29084612204565b60055560405133907f98220ba7e456cda59b84320240d405cb87d7d871ba13f798d6362297818d29fc90600090a26040516000906001600160a01b0386169085908381818185875af1925050503d8060008114610a5b576040519150601f19603f3d011682016040523d82523d6000602084013e610a60565b606091505b5050905080610a9e576040805162461bcd60e51b815260206004820152600560248201526432b93937b960d91b604482015290519081900360640190fd5b505060016002555047610aaf612265565b11156040518060400160405280600f81526020016e62616c616e636520746f6f206c6f7760881b81525090610b255760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b50919050565b600454600754600554919260009290910190565b600360208190526000918252604090912080546001820154600283015492909301549092919084565b60065481565b6000600854600014158015610b84575042600854105b6040518060400160405280600b81526020016a1b9bdd081cdd185c9d195960aa1b81525090610bf45760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b50610bfe3361228a565b905090565b60008054600160a81b900460ff16610c26576000546001600160a01b0316610bfe565b60076001609c1b016001600160a01b031663732524946040518163ffffffff1660e01b815260040160206040518083038186803b158015610c6657600080fd5b505afa158015610c7a573d6000803e3d6000fd5b505050506040513d6020811015610c9057600080fd5b5051905090565b60408051630debfda360e41b8152336004820152905160076001609c1b019163debfda30916024808301926020929190829003018186803b158015610cdb57600080fd5b505afa158015610cef573d6000803e3d6000fd5b505050506040513d6020811015610d0557600080fd5b5051610d48576040805162461bcd60e51b815260206004820152600d60248201526c37b7363c9032bc32b1baba37b960991b604482015290519081900360640190fd5b6001600160e01b0319811660009081526001602052604090208054610db4576040805162461bcd60e51b815260206004820152601a60248201527f74696d656c6f636b3a20696e76616c69642073656c6563746f72000000000000604482015290519081900360640190fd5b8054421015610e0a576040805162461bcd60e51b815260206004820152601960248201527f74696d656c6f636b3a206e6f7420616c6c6f7765642079657400000000000000604482015290519081900360640190fd5b6000816001018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610ea45780601f10610e7957610100808354040283529160200191610ea4565b820191906000526020600020905b815481529060010190602001808311610e8757829003601f168201915b5050506001600160e01b0319861660009081526001602081905260408220828155949550909250610ed89150830182612afd565b50506000805460ff60b01b1916600160b01b178155604051825130918491819060208401908083835b60208310610f205780518252601f199092019160209182019101610f01565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610f82576040519150601f19603f3d011682016040523d82523d6000602084013e610f87565b606091505b50506000805460ff60b01b19169055604080516001600160e01b03198716815242602082015281519293507fa7326b57fc9cfe267aaea5e7f0b01757154d265620a0585819416ee9ddd2c438929081900390910190a1610fe681612517565b50505050565b600054600160b01b900460ff168061100e5750600054600160a81b900460ff16155b156113485761101b612534565b604080518082019091526008815267746f6f206d616e7960c01b60208201526103e884111561108b5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b5060408051808201909152601781527f617272617973206c656e67746873206d69736d61746368000000000000000000602082015283821461110e5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b5060085460408051808201909152600f81526e185b1c9958591e481cdd185c9d1959608a1b602082015290156111855760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b506000600360008686600081811061119957fe5b905060200201356001600160a01b03166001600160a01b03166001600160a01b031681526020019081526020016000206000015411156111d857611343565b60005b61ffff81168411156112de5760006112186105dc61271086868661ffff1681811061120257fe5b9050602002013561256b9092919063ffffffff16565b905060006112458286868661ffff1681811061123057fe5b9050602002013561267190919063ffffffff16565b905060405180608001604052808281526020016000815260200160008152602001838152506003600089898761ffff1681811061127e57fe5b602090810292909201356001600160a01b03168352508181019290925260409081016000208351815591830151600183015582015160028201556060909101516003909101556004546112d19082612204565b60045550506001016111db565b507fc21490756c6f0185a8ad2363084fd0a45b06707979f77786b5e681bddc1d2fa1848460405180806020018281038252848482818152602001925060200280828437600083820152604051601f909101601f19169092018290039550909350505050a15b610fe6565b610fe66000366126ce565b7f000000000000000000000000000000000000000000000000000000000000000081565b60076001609c1b0181565b61138a612851565b6001600160e01b031981166000908152600160205260409020546113f5576040805162461bcd60e51b815260206004820152601a60248201527f74696d656c6f636b3a20696e76616c69642073656c6563746f72000000000000604482015290519081900360640190fd5b604080516001600160e01b03198316815242602082015281517f7735b2391c38a81419c513e30ca578db7158eadd7101511b23e221c654d19cf8929181900390910190a16001600160e01b0319811660009081526001602081905260408220828155919061146590830182612afd565b505050565b600160208181526000928352604092839020805481840180548651600296821615610100026000190190911695909504601f810185900485028601850190965285855290949193929091908301828280156115065780601f106114db57610100808354040283529160200191611506565b820191906000526020600020905b8154815290600101906020018083116114e957829003601f168201915b5050505050905082565b6000600854600014158015611526575042600854105b6040518060400160405280600b81526020016a1b9bdd081cdd185c9d195960aa1b815250906115965760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b506115a082611fa2565b92915050565b600054600160a01b900460ff16156115fc576040805162461bcd60e51b8152602060048201526014602482015273696e697469616c6973656420213d2066616c736560601b604482015290519081900360640190fd5b60008054600160a01b60ff60a01b19909116176001600160a01b0319166001600160a01b03831690811790915560408051918252517f9789733827840833afc031fb2ef9ab6894271f77bad2085687cf4ae5c7bee4db916020908290030190a150565b60055481565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008054600160b01b900460ff16806116ac5750600054600160a81b900460ff16155b1561194d576116b9612534565b600854158015906116cb575042600854105b6040518060400160405280600b81526020016a1b9bdd081cdd185c9d195960aa1b8152509061173b5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b506000600654116040518060400160405280601e81526020017f6e6f2062616c616e63652063757272656e746c7920617661696c61626c650000815250906117c45760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b5060075460065414156040518060400160405280601e81526020017f6e6f2062616c616e63652063757272656e746c7920617661696c61626c6500008152509061184f5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b5060075460065461185f91612671565b6006546007556040519091507f79d406fa3c1c020905a48c371f891e33f8210c0e4ab4d5221dc01f531f7342db90600090a16040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156118c7573d6000803e3d6000fd5b50476118d1612265565b11156040518060400160405280600f81526020016e62616c616e636520746f6f206c6f7760881b815250906119475760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b50611958565b6119586000366126ce565b919050565b6000600854600014158015611973575042600854105b6040518060400160405280600b81526020016a1b9bdd081cdd185c9d195960aa1b815250906119e35760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b50610bfe33611fa2565b600054600160a81b900460ff1681565b600054600160b01b900460ff1680611a1f5750600054600160a81b900460ff16155b15611c4b57611a2c612534565b6008541580611a3c575042600854115b6040518060400160405280600f81526020016e185b1c9958591e481cdd185c9d1959608a1b81525090611ab05760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b50428110158015611ae157507f00000000000000000000000000000000000000000000000000000000000000008111155b60405180604001604052806015815260200174077726f6e672073746172742074696d657374616d7605c1b81525090611b5b5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b506004547f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031631101580611b9957506004544710155b6040518060400160405280600f81526020016e62616c616e636520746f6f206c6f7760881b81525090611c0d5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b5060088190556040805182815290517f6887b4fbe6e282072c586eed840058a3507439898b1521541253e5a78a41c69b9181900360200190a1611c56565b611c566000366126ce565b50565b60085481565b60045481565b33600081815260036020818152604092839020909101548251808401909352600e83526d1b9bdd081c9959da5cdd195c995960921b91830191909152611cec5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b506001600160a01b0381166000908152600360209081526040918290206002015482518084019093526011835270185b1c9958591e481bdc1d1959081bdd5d607a1b9183019190915215611d815760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b5060085415801590611d94575042600854105b6040518060400160405280600b81526020016a1b9bdd081cdd185c9d195960aa1b81525090611e045760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b50336000908152600360209081526040918290206001810154815484518086019095526015855274185b1c9958591e48199d5b1b1e4818db185a5b5959605a1b9385019390935290929111611e9a5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b5060405133907fdaa99ea0f252dcde78c690a59f1d9953dcca69dc3127eff6f919fc8b16ed873090600090a2600181015481540360028201819055600654611ee191612204565b6006555050565b611ef0612851565b600054600160a81b900460ff1615611f4f576040805162461bcd60e51b815260206004820152601a60248201527f616c726561647920696e2070726f64756374696f6e206d6f6465000000000000604482015290519081900360640190fd5b60008054600161ff0160a01b031916600160a81b1790556040805160076001609c1b01815290517f83af113638b5422f9e977cebc0aaf0eaf2188eb9a8baae7f9d46c42b33a1560c9181900360200190a1565b6000600854600014158015611fb8575042600854105b6040518060400160405280600b81526020016a1b9bdd081cdd185c9d195960aa1b815250906120285760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b508160036000826001600160a01b03166001600160a01b0316815260200190815260200160002060030154600014156040518060400160405280600e81526020016d1b9bdd081c9959da5cdd195c995960921b815250906120ca5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b506001600160a01b0381166000908152600360209081526040918290206002015482518084019093526011835270185b1c9958591e481bdc1d1959081bdd5d607a1b918301919091521561215f5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b506001600160a01b0383166000908152600360208181526040808420815160808101835281548152600182015493810193909352600281015491830191909152909101546060820152906121b16128b0565b82519091506000906121c6908361213461256b565b90506121de6121d9828560000151612978565b61298e565b6fffffffffffffffffffffffffffffffff16905082602001518103945050505050919050565b60008282018381101561225e576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000610bfe60075461228460055460045461267190919063ffffffff16565b90612671565b60006008546000141580156122a0575042600854105b6040518060400160405280600b81526020016a1b9bdd081cdd185c9d195960aa1b815250906123105760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b508160036000826001600160a01b03166001600160a01b0316815260200190815260200160002060030154600014156040518060400160405280600e81526020016d1b9bdd081c9959da5cdd195c995960921b815250906123b25760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b506001600160a01b0381166000908152600360209081526040918290206002015482518084019093526011835270185b1c9958591e481bdc1d1959081bdd5d607a1b91830191909152156124475760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b50602461246c62278d006124666008544261267190919063ffffffff16565b906129d6565b1060405180604001604052806015815260200174185b1c9958591e48199d5b1b1e4818db185a5b5959605a1b815250906124e75760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b5061225e61250d62278d006125076008544261267190919063ffffffff16565b90612a3d565b62278d0090612671565b3d604051818101604052816000823e8215612530578181f35b8181fd5b600054600160b01b900460ff16156125615733301461254f57fe5b6000805460ff60b01b19169055612569565b612569612851565b565b60008082116125b4576040805162461bcd60e51b815260206004820152601060248201526f4469766973696f6e206279207a65726f60801b604482015290519081900360640190fd5b836125c15750600061225e565b838302838582816125ce57fe5b0414156125e7578281816125de57fe5b0491505061225e565b60008386816125f257fe5b049050600084878161260057fe5b069050600085878161260e57fe5b049050600086888161261c57fe5b069050612664612630886124668685612aa4565b61265e61263d8686612aa4565b61265e61264a8987612aa4565b61265e8d6126588c8b612aa4565b90612aa4565b90612204565b9998505050505050505050565b6000828211156126c8576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6126d6612851565b600082359050600060076001609c1b016001600160a01b0316636221a54b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561271e57600080fd5b505afa158015612732573d6000803e3d6000fd5b505050506040513d602081101561274857600080fd5b505160408051808201825242830180825282516020601f89018190048102820181019094528781529394509290918281019190889088908190840183828082843760009201829052509390945250506001600160e01b031986168152600160208181526040909220845181558483015180519194506127cc93928501920190612b41565b509050507fed948300a3694aa01d4a6b258bfd664350193d770c0b51f8387277f6d83ea3b68382878760405180856001600160e01b0319168152602001848152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f191690920182900397509095505050505050a15050505050565b612859610c03565b6001600160a01b0316336001600160a01b031614612569576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920676f7665726e616e636560881b604482015290519081900360640190fd5b60006008546000141580156128c6575042600854105b6040518060400160405280600b81526020016a1b9bdd081cdd185c9d195960aa1b815250906129365760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b506000612955620151806124666008544261267190919063ffffffff16565b905061297261296a60ed61265884601e6129d6565b612134612978565b91505090565b6000818310612987578161225e565b5090919050565b6000600160801b82106129d25760405162461bcd60e51b8152600401808060200182810382526027815260200180612bdb6027913960400191505060405180910390fd5b5090565b6000808211612a2c576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381612a3557fe5b049392505050565b6000808211612a93576040805162461bcd60e51b815260206004820152601860248201527f536166654d6174683a206d6f64756c6f206279207a65726f0000000000000000604482015290519081900360640190fd5b818381612a9c57fe5b069392505050565b600082612ab3575060006115a0565b82820282848281612ac057fe5b041461225e5760405162461bcd60e51b8152600401808060200182810382526021815260200180612c026021913960400191505060405180910390fd5b50805460018160011615610100020316600290046000825580601f10612b235750611c56565b601f016020900490600052602060002090810190611c569190612bc5565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282612b775760008555612bbd565b82601f10612b9057805160ff1916838001178555612bbd565b82800160010185558215612bbd579182015b82811115612bbd578251825591602001919060010190612ba2565b506129d29291505b5b808211156129d25760008155600101612bc656fe53616665436173743a2076616c756520646f65736e27742066697420696e203132382062697473536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a264697066735822122022cd343cbe905a8cc180ebbb51b7ae7ba4f794c1f940ad102ebd0933521bf79964736f6c634300070600330000000000000000000000004598a6c05910ab914f0cbaaca1911cd337d10d2900000000000000000000000010000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000064602480

Deployed ByteCode

0x6080604052600436106101695760003560e01c806374e6310e116100d1578063c354bd6e1161008a578063e60eb6ff11610064578063e60eb6ff146106d0578063f2325e38146106e5578063f2a1f767146106fa578063f5a983831461070f57610249565b8063c354bd6e14610668578063e17f212e1461067d578063e28ef1f7146106a657610249565b806374e6310e146104f25780637fd45d2b146105a55780639d6a890f146105d85780639f71043e1461060b578063ae67716114610620578063b5551ab71461063557610249565b80635aa6e675116101235780635aa6e6751461035e5780635ff270791461038f57806361235585146103c557806361d027b31461049457806362354e03146104a957806367fc4029146104be57610249565b80626a1d511461024e5780631e83409a146102755780632dafdbbf146102a857806344a8ace2146102db57806344d94b4b146103345780634bb5696a1461034957610249565b366102495760408051808201909152600d81526c7472656173757279206f6e6c7960981b6020820152336001600160a01b037f000000000000000000000000100000000000000000000000000000000000000416146102465760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561020b5781810151838201526020016101f3565b50505050905090810190601f1680156102385780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50005b600080fd5b34801561025a57600080fd5b50610263610724565b60408051918252519081900360200190f35b34801561028157600080fd5b506102636004803603602081101561029857600080fd5b50356001600160a01b031661072a565b3480156102b457600080fd5b506102bd610b2b565b60408051938452602084019290925282820152519081900360600190f35b3480156102e757600080fd5b5061030e600480360360208110156102fe57600080fd5b50356001600160a01b0316610b3f565b604080519485526020850193909352838301919091526060830152519081900360800190f35b34801561034057600080fd5b50610263610b68565b34801561035557600080fd5b50610263610b6e565b34801561036a57600080fd5b50610373610c03565b604080516001600160a01b039092168252519081900360200190f35b34801561039b57600080fd5b506103c3600480360360208110156103b257600080fd5b50356001600160e01b031916610c97565b005b3480156103d157600080fd5b506103c3600480360360408110156103e857600080fd5b81019060208101813564010000000081111561040357600080fd5b82018360208201111561041557600080fd5b8035906020019184602083028401116401000000008311171561043757600080fd5b91939092909160208101903564010000000081111561045557600080fd5b82018360208201111561046757600080fd5b8035906020019184602083028401116401000000008311171561048957600080fd5b509092509050610fec565b3480156104a057600080fd5b50610373611353565b3480156104b557600080fd5b50610373611377565b3480156104ca57600080fd5b506103c3600480360360208110156104e157600080fd5b50356001600160e01b031916611382565b3480156104fe57600080fd5b506105266004803603602081101561051557600080fd5b50356001600160e01b03191661146a565b6040518083815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610569578181015183820152602001610551565b50505050905090810190601f1680156105965780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b3480156105b157600080fd5b50610263600480360360208110156105c857600080fd5b50356001600160a01b0316611510565b3480156105e457600080fd5b506103c3600480360360208110156105fb57600080fd5b50356001600160a01b03166115a6565b34801561061757600080fd5b5061026361165f565b34801561062c57600080fd5b50610263611665565b34801561064157600080fd5b506102636004803603602081101561065857600080fd5b50356001600160a01b0316611689565b34801561067457600080fd5b5061026361195d565b34801561068957600080fd5b506106926119ed565b604080519115158252519081900360200190f35b3480156106b257600080fd5b506103c3600480360360208110156106c957600080fd5b50356119fd565b3480156106dc57600080fd5b50610263611c59565b3480156106f157600080fd5b50610263611c5f565b34801561070657600080fd5b506103c3611c65565b34801561071b57600080fd5b506103c3611ee8565b60075481565b6000600854600014158015610740575042600854105b6040518060400160405280600b81526020016a1b9bdd081cdd185c9d195960aa1b815250906107b05760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b50600280541415610808576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002805533600081815260036020818152604092839020909101548251808401909352600e83526d1b9bdd081c9959da5cdd195c995960921b918301919091526108935760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b506001600160a01b0381166000908152600360209081526040918290206002015482518084019093526011835270185b1c9958591e481bdc1d1959081bdd5d607a1b91830191909152156109285760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b503360008181526003602052604090209061094290611fa2565b9250600083116040518060400160405280601e81526020017f6e6f2062616c616e63652063757272656e746c7920617661696c61626c650000815250906109ca5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b50600181018054840190556005546109e29084612204565b60055560405133907f98220ba7e456cda59b84320240d405cb87d7d871ba13f798d6362297818d29fc90600090a26040516000906001600160a01b0386169085908381818185875af1925050503d8060008114610a5b576040519150601f19603f3d011682016040523d82523d6000602084013e610a60565b606091505b5050905080610a9e576040805162461bcd60e51b815260206004820152600560248201526432b93937b960d91b604482015290519081900360640190fd5b505060016002555047610aaf612265565b11156040518060400160405280600f81526020016e62616c616e636520746f6f206c6f7760881b81525090610b255760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b50919050565b600454600754600554919260009290910190565b600360208190526000918252604090912080546001820154600283015492909301549092919084565b60065481565b6000600854600014158015610b84575042600854105b6040518060400160405280600b81526020016a1b9bdd081cdd185c9d195960aa1b81525090610bf45760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b50610bfe3361228a565b905090565b60008054600160a81b900460ff16610c26576000546001600160a01b0316610bfe565b60076001609c1b016001600160a01b031663732524946040518163ffffffff1660e01b815260040160206040518083038186803b158015610c6657600080fd5b505afa158015610c7a573d6000803e3d6000fd5b505050506040513d6020811015610c9057600080fd5b5051905090565b60408051630debfda360e41b8152336004820152905160076001609c1b019163debfda30916024808301926020929190829003018186803b158015610cdb57600080fd5b505afa158015610cef573d6000803e3d6000fd5b505050506040513d6020811015610d0557600080fd5b5051610d48576040805162461bcd60e51b815260206004820152600d60248201526c37b7363c9032bc32b1baba37b960991b604482015290519081900360640190fd5b6001600160e01b0319811660009081526001602052604090208054610db4576040805162461bcd60e51b815260206004820152601a60248201527f74696d656c6f636b3a20696e76616c69642073656c6563746f72000000000000604482015290519081900360640190fd5b8054421015610e0a576040805162461bcd60e51b815260206004820152601960248201527f74696d656c6f636b3a206e6f7420616c6c6f7765642079657400000000000000604482015290519081900360640190fd5b6000816001018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610ea45780601f10610e7957610100808354040283529160200191610ea4565b820191906000526020600020905b815481529060010190602001808311610e8757829003601f168201915b5050506001600160e01b0319861660009081526001602081905260408220828155949550909250610ed89150830182612afd565b50506000805460ff60b01b1916600160b01b178155604051825130918491819060208401908083835b60208310610f205780518252601f199092019160209182019101610f01565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610f82576040519150601f19603f3d011682016040523d82523d6000602084013e610f87565b606091505b50506000805460ff60b01b19169055604080516001600160e01b03198716815242602082015281519293507fa7326b57fc9cfe267aaea5e7f0b01757154d265620a0585819416ee9ddd2c438929081900390910190a1610fe681612517565b50505050565b600054600160b01b900460ff168061100e5750600054600160a81b900460ff16155b156113485761101b612534565b604080518082019091526008815267746f6f206d616e7960c01b60208201526103e884111561108b5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b5060408051808201909152601781527f617272617973206c656e67746873206d69736d61746368000000000000000000602082015283821461110e5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b5060085460408051808201909152600f81526e185b1c9958591e481cdd185c9d1959608a1b602082015290156111855760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b506000600360008686600081811061119957fe5b905060200201356001600160a01b03166001600160a01b03166001600160a01b031681526020019081526020016000206000015411156111d857611343565b60005b61ffff81168411156112de5760006112186105dc61271086868661ffff1681811061120257fe5b9050602002013561256b9092919063ffffffff16565b905060006112458286868661ffff1681811061123057fe5b9050602002013561267190919063ffffffff16565b905060405180608001604052808281526020016000815260200160008152602001838152506003600089898761ffff1681811061127e57fe5b602090810292909201356001600160a01b03168352508181019290925260409081016000208351815591830151600183015582015160028201556060909101516003909101556004546112d19082612204565b60045550506001016111db565b507fc21490756c6f0185a8ad2363084fd0a45b06707979f77786b5e681bddc1d2fa1848460405180806020018281038252848482818152602001925060200280828437600083820152604051601f909101601f19169092018290039550909350505050a15b610fe6565b610fe66000366126ce565b7f000000000000000000000000100000000000000000000000000000000000000481565b60076001609c1b0181565b61138a612851565b6001600160e01b031981166000908152600160205260409020546113f5576040805162461bcd60e51b815260206004820152601a60248201527f74696d656c6f636b3a20696e76616c69642073656c6563746f72000000000000604482015290519081900360640190fd5b604080516001600160e01b03198316815242602082015281517f7735b2391c38a81419c513e30ca578db7158eadd7101511b23e221c654d19cf8929181900390910190a16001600160e01b0319811660009081526001602081905260408220828155919061146590830182612afd565b505050565b600160208181526000928352604092839020805481840180548651600296821615610100026000190190911695909504601f810185900485028601850190965285855290949193929091908301828280156115065780601f106114db57610100808354040283529160200191611506565b820191906000526020600020905b8154815290600101906020018083116114e957829003601f168201915b5050505050905082565b6000600854600014158015611526575042600854105b6040518060400160405280600b81526020016a1b9bdd081cdd185c9d195960aa1b815250906115965760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b506115a082611fa2565b92915050565b600054600160a01b900460ff16156115fc576040805162461bcd60e51b8152602060048201526014602482015273696e697469616c6973656420213d2066616c736560601b604482015290519081900360640190fd5b60008054600160a01b60ff60a01b19909116176001600160a01b0319166001600160a01b03831690811790915560408051918252517f9789733827840833afc031fb2ef9ab6894271f77bad2085687cf4ae5c7bee4db916020908290030190a150565b60055481565b7f000000000000000000000000000000000000000000000000000000006460248081565b60008054600160b01b900460ff16806116ac5750600054600160a81b900460ff16155b1561194d576116b9612534565b600854158015906116cb575042600854105b6040518060400160405280600b81526020016a1b9bdd081cdd185c9d195960aa1b8152509061173b5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b506000600654116040518060400160405280601e81526020017f6e6f2062616c616e63652063757272656e746c7920617661696c61626c650000815250906117c45760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b5060075460065414156040518060400160405280601e81526020017f6e6f2062616c616e63652063757272656e746c7920617661696c61626c6500008152509061184f5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b5060075460065461185f91612671565b6006546007556040519091507f79d406fa3c1c020905a48c371f891e33f8210c0e4ab4d5221dc01f531f7342db90600090a16040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156118c7573d6000803e3d6000fd5b50476118d1612265565b11156040518060400160405280600f81526020016e62616c616e636520746f6f206c6f7760881b815250906119475760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b50611958565b6119586000366126ce565b919050565b6000600854600014158015611973575042600854105b6040518060400160405280600b81526020016a1b9bdd081cdd185c9d195960aa1b815250906119e35760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b50610bfe33611fa2565b600054600160a81b900460ff1681565b600054600160b01b900460ff1680611a1f5750600054600160a81b900460ff16155b15611c4b57611a2c612534565b6008541580611a3c575042600854115b6040518060400160405280600f81526020016e185b1c9958591e481cdd185c9d1959608a1b81525090611ab05760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b50428110158015611ae157507f00000000000000000000000000000000000000000000000000000000646024808111155b60405180604001604052806015815260200174077726f6e672073746172742074696d657374616d7605c1b81525090611b5b5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b506004547f00000000000000000000000010000000000000000000000000000000000000046001600160a01b031631101580611b9957506004544710155b6040518060400160405280600f81526020016e62616c616e636520746f6f206c6f7760881b81525090611c0d5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b5060088190556040805182815290517f6887b4fbe6e282072c586eed840058a3507439898b1521541253e5a78a41c69b9181900360200190a1611c56565b611c566000366126ce565b50565b60085481565b60045481565b33600081815260036020818152604092839020909101548251808401909352600e83526d1b9bdd081c9959da5cdd195c995960921b91830191909152611cec5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b506001600160a01b0381166000908152600360209081526040918290206002015482518084019093526011835270185b1c9958591e481bdc1d1959081bdd5d607a1b9183019190915215611d815760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b5060085415801590611d94575042600854105b6040518060400160405280600b81526020016a1b9bdd081cdd185c9d195960aa1b81525090611e045760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b50336000908152600360209081526040918290206001810154815484518086019095526015855274185b1c9958591e48199d5b1b1e4818db185a5b5959605a1b9385019390935290929111611e9a5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b5060405133907fdaa99ea0f252dcde78c690a59f1d9953dcca69dc3127eff6f919fc8b16ed873090600090a2600181015481540360028201819055600654611ee191612204565b6006555050565b611ef0612851565b600054600160a81b900460ff1615611f4f576040805162461bcd60e51b815260206004820152601a60248201527f616c726561647920696e2070726f64756374696f6e206d6f6465000000000000604482015290519081900360640190fd5b60008054600161ff0160a01b031916600160a81b1790556040805160076001609c1b01815290517f83af113638b5422f9e977cebc0aaf0eaf2188eb9a8baae7f9d46c42b33a1560c9181900360200190a1565b6000600854600014158015611fb8575042600854105b6040518060400160405280600b81526020016a1b9bdd081cdd185c9d195960aa1b815250906120285760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b508160036000826001600160a01b03166001600160a01b0316815260200190815260200160002060030154600014156040518060400160405280600e81526020016d1b9bdd081c9959da5cdd195c995960921b815250906120ca5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b506001600160a01b0381166000908152600360209081526040918290206002015482518084019093526011835270185b1c9958591e481bdc1d1959081bdd5d607a1b918301919091521561215f5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b506001600160a01b0383166000908152600360208181526040808420815160808101835281548152600182015493810193909352600281015491830191909152909101546060820152906121b16128b0565b82519091506000906121c6908361213461256b565b90506121de6121d9828560000151612978565b61298e565b6fffffffffffffffffffffffffffffffff16905082602001518103945050505050919050565b60008282018381101561225e576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000610bfe60075461228460055460045461267190919063ffffffff16565b90612671565b60006008546000141580156122a0575042600854105b6040518060400160405280600b81526020016a1b9bdd081cdd185c9d195960aa1b815250906123105760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b508160036000826001600160a01b03166001600160a01b0316815260200190815260200160002060030154600014156040518060400160405280600e81526020016d1b9bdd081c9959da5cdd195c995960921b815250906123b25760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b506001600160a01b0381166000908152600360209081526040918290206002015482518084019093526011835270185b1c9958591e481bdc1d1959081bdd5d607a1b91830191909152156124475760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b50602461246c62278d006124666008544261267190919063ffffffff16565b906129d6565b1060405180604001604052806015815260200174185b1c9958591e48199d5b1b1e4818db185a5b5959605a1b815250906124e75760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b5061225e61250d62278d006125076008544261267190919063ffffffff16565b90612a3d565b62278d0090612671565b3d604051818101604052816000823e8215612530578181f35b8181fd5b600054600160b01b900460ff16156125615733301461254f57fe5b6000805460ff60b01b19169055612569565b612569612851565b565b60008082116125b4576040805162461bcd60e51b815260206004820152601060248201526f4469766973696f6e206279207a65726f60801b604482015290519081900360640190fd5b836125c15750600061225e565b838302838582816125ce57fe5b0414156125e7578281816125de57fe5b0491505061225e565b60008386816125f257fe5b049050600084878161260057fe5b069050600085878161260e57fe5b049050600086888161261c57fe5b069050612664612630886124668685612aa4565b61265e61263d8686612aa4565b61265e61264a8987612aa4565b61265e8d6126588c8b612aa4565b90612aa4565b90612204565b9998505050505050505050565b6000828211156126c8576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6126d6612851565b600082359050600060076001609c1b016001600160a01b0316636221a54b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561271e57600080fd5b505afa158015612732573d6000803e3d6000fd5b505050506040513d602081101561274857600080fd5b505160408051808201825242830180825282516020601f89018190048102820181019094528781529394509290918281019190889088908190840183828082843760009201829052509390945250506001600160e01b031986168152600160208181526040909220845181558483015180519194506127cc93928501920190612b41565b509050507fed948300a3694aa01d4a6b258bfd664350193d770c0b51f8387277f6d83ea3b68382878760405180856001600160e01b0319168152602001848152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f191690920182900397509095505050505050a15050505050565b612859610c03565b6001600160a01b0316336001600160a01b031614612569576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920676f7665726e616e636560881b604482015290519081900360640190fd5b60006008546000141580156128c6575042600854105b6040518060400160405280600b81526020016a1b9bdd081cdd185c9d195960aa1b815250906129365760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561020b5781810151838201526020016101f3565b506000612955620151806124666008544261267190919063ffffffff16565b905061297261296a60ed61265884601e6129d6565b612134612978565b91505090565b6000818310612987578161225e565b5090919050565b6000600160801b82106129d25760405162461bcd60e51b8152600401808060200182810382526027815260200180612bdb6027913960400191505060405180910390fd5b5090565b6000808211612a2c576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381612a3557fe5b049392505050565b6000808211612a93576040805162461bcd60e51b815260206004820152601860248201527f536166654d6174683a206d6f64756c6f206279207a65726f0000000000000000604482015290519081900360640190fd5b818381612a9c57fe5b069392505050565b600082612ab3575060006115a0565b82820282848281612ac057fe5b041461225e5760405162461bcd60e51b8152600401808060200182810382526021815260200180612c026021913960400191505060405180910390fd5b50805460018160011615610100020316600290046000825580601f10612b235750611c56565b601f016020900490600052602060002090810190611c569190612bc5565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282612b775760008555612bbd565b82601f10612b9057805160ff1916838001178555612bbd565b82800160010185558215612bbd579182015b82811115612bbd578251825591602001919060010190612ba2565b506129d29291505b5b808211156129d25760008155600101612bc656fe53616665436173743a2076616c756520646f65736e27742066697420696e203132382062697473536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a264697066735822122022cd343cbe905a8cc180ebbb51b7ae7ba4f794c1f940ad102ebd0933521bf79964736f6c63430007060033