Contract 0xCd39Ca01844b07c47f19d7Aca120F9681e9dd33A 2

 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x288a8dbac40bc440cb94d4a74880291376ce5e5c3f9c67299b5ab035dd8816790x608060401954318572024-03-29 12:18:2321 days 16 hrs ago0x4772730d06a0853997eede965906e5d0290e25df IN  Create: StakingThales0 ETH0.000162620.01
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
StakingThales

Compiler Version
v0.5.16+commit.9c3226ce

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 26 : StakingThales.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.5.16;

import "openzeppelin-solidity-2.3.0/contracts/token/ERC20/SafeERC20.sol";
import "openzeppelin-solidity-2.3.0/contracts/math/SafeMath.sol";

import "../utils/proxy/ProxyReentrancyGuard.sol";
import "../utils/proxy/ProxyOwned.sol";
import "../utils/proxy/ProxyPausable.sol";
import "@openzeppelin/upgrades-core/contracts/Initializable.sol";

import "../interfaces/IEscrowThales.sol";
import "../interfaces/IStakingThales.sol";
import "../interfaces/ISNXRewards.sol";
import "../interfaces/IThalesRoyale.sol";
import "../interfaces/IPriceFeed.sol";
import "../interfaces/IThalesStakingRewardsPool.sol";
import "../interfaces/IAddressResolver.sol";
import "../interfaces/ISportsAMMLiquidityPool.sol";
import "../interfaces/IThalesAMMLiquidityPool.sol";
import "../interfaces/IParlayAMMLiquidityPool.sol";
import "../interfaces/IThalesAMM.sol";
import "../interfaces/IPositionalMarketManager.sol";
import "../interfaces/IStakingThalesBonusRewardsManager.sol";
import "../interfaces/ICCIPCollector.sol";

/// @title A Staking contract that provides logic for staking and claiming rewards
contract StakingThales is IStakingThales, Initializable, ProxyOwned, ProxyReentrancyGuard, ProxyPausable {
    /* ========== LIBRARIES ========== */

    using SafeMath for uint;
    using SafeERC20 for IERC20;

    /* ========== STATE VARIABLES ========== */

    IEscrowThales public iEscrowThales;
    IERC20 public stakingToken;
    IERC20 public feeToken;
    ISNXRewards private SNXRewards;
    IThalesRoyale private thalesRoyale;
    IPriceFeed public priceFeed;

    uint public periodsOfStaking;
    uint public lastPeriodTimeStamp;
    uint public durationPeriod;
    uint public unstakeDurationPeriod;
    uint public startTimeStamp;
    uint public currentPeriodRewards;
    uint public currentPeriodFees;
    bool public distributeFeesEnabled;
    uint public fixedPeriodReward;
    uint public periodExtraReward;
    uint private totalSNXRewardsInPeriod;
    uint private totalSNXFeesInPeriod;
    bool public claimEnabled;

    mapping(address => uint) public stakerLifetimeRewardsClaimed;
    mapping(address => uint) public stakerFeesClaimed;

    uint private _totalStakedAmount;
    uint private _totalEscrowedAmount;
    uint private _totalPendingStakeAmount;
    uint private _totalUnclaimedRewards;
    uint private _totalRewardsClaimed;
    uint private _totalRewardFeesClaimed;

    mapping(address => uint) public lastUnstakeTime;
    mapping(address => bool) public unstaking;
    mapping(address => uint) public unstakingAmount;
    mapping(address => uint) private _stakedBalances;
    mapping(address => uint) private _lastRewardsClaimedPeriod;
    address public thalesAMM;

    uint constant HUNDRED = 1e18;
    uint constant AMM_EXTRA_REWARD_PERIODS = 4;

    struct AMMVolumeEntry {
        uint amount;
        uint period;
    }
    mapping(address => uint) private lastAMMUpdatePeriod;
    mapping(address => AMMVolumeEntry[AMM_EXTRA_REWARD_PERIODS]) private stakerAMMVolume;

    bool public extraRewardsActive;
    IThalesStakingRewardsPool public ThalesStakingRewardsPool;

    uint private maxSNXRewardsPercentage;
    uint private maxAMMVolumeRewardsPercentage;
    uint private AMMVolumeRewardsMultiplier;
    uint private maxThalesRoyaleRewardsPercentage;

    uint constant ONE = 1e18;
    uint constant ONE_PERCENT = 1e16;

    uint private SNXVolumeRewardsMultiplier;

    mapping(address => uint) private _lastStakingPeriod;

    uint public totalStakedLastPeriodEnd;
    uint public totalEscrowedLastPeriodEnd;
    address private exoticBonds;

    IAddressResolver private addressResolver;

    address public thalesRangedAMM;
    address public sportsAMM;

    mapping(address => uint) private lastThalesAMMUpdatePeriod;
    mapping(address => AMMVolumeEntry[AMM_EXTRA_REWARD_PERIODS]) private thalesAMMVolume;
    mapping(address => uint) private lastThalesRangedAMMUpdatePeriod;
    mapping(address => AMMVolumeEntry[AMM_EXTRA_REWARD_PERIODS]) private thalesRangedAMMVolume;
    mapping(address => uint) private lastExoticMarketsUpdatePeriod;
    mapping(address => AMMVolumeEntry[AMM_EXTRA_REWARD_PERIODS]) private exoticMarketsVolume;
    mapping(address => uint) private lastSportsAMMUpdatePeriod;
    mapping(address => AMMVolumeEntry[AMM_EXTRA_REWARD_PERIODS]) private sportsAMMVolume;

    mapping(address => mapping(address => bool)) public canClaimOnBehalf;

    bool public mergeAccountEnabled;

    mapping(address => address) public delegatedVolume;
    mapping(address => bool) public supportedSportVault;
    mapping(address => bool) public supportedAMMVault;

    ISportsAMMLiquidityPool private sportsAMMLiquidityPool;
    IThalesAMMLiquidityPool private thalesAMMLiquidityPool;

    IStakingThalesBonusRewardsManager public stakingThalesBonusRewardsManager;
    IParlayAMMLiquidityPool private parlayAMMLiquidityPool;

    bool public readOnlyMode;
    bool public closingPeriodInProgress;
    uint public closingPeriodPauseTime;

    bool public sendCCIPMessage;

    /* ========== CONSTRUCTOR ========== */

    function initialize(
        address _owner,
        address _iEscrowThales, //THALES
        address _stakingToken, //THALES
        address _feeToken, //sUSD
        uint _durationPeriod,
        uint _unstakeDurationPeriod,
        address _ISNXRewards
    ) public initializer {
        setOwner(_owner);
        initNonReentrant();
        iEscrowThales = IEscrowThales(_iEscrowThales);
        stakingToken = IERC20(_stakingToken);
        feeToken = IERC20(_feeToken);
        stakingToken.approve(_iEscrowThales, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
        durationPeriod = _durationPeriod;
        unstakeDurationPeriod = _unstakeDurationPeriod;
        fixedPeriodReward = 70000 * 1e18;
        periodExtraReward = 21000 * 1e18;
        SNXRewards = ISNXRewards(_ISNXRewards);
    }

    /* ========== VIEWS ========== */

    /// @notice Get the total staked amount on the contract
    /// @return total staked amount
    function totalStakedAmount() external view returns (uint) {
        return _totalStakedAmount;
    }

    /// @notice Get the staked balance for the account
    /// @param account to get the staked balance for
    /// @return the staked balance for the account
    function stakedBalanceOf(address account) external view returns (uint) {
        return _stakedBalances[account];
    }

    /// @notice Get the last period of claimed rewards for the account
    /// @param account to get the last period of claimed rewards for
    /// @return the last period of claimed rewards for the account
    function getLastPeriodOfClaimedRewards(address account) external view returns (uint) {
        return _lastRewardsClaimedPeriod[account];
    }

    /// @notice Get the rewards available for the claim for the account
    /// @param account to get the rewards available for the claim for
    /// @return the rewards available for the claim for the account
    function getRewardsAvailable(address account) external view returns (uint) {
        return _calculateAvailableRewardsToClaim(account);
    }

    /// @notice Get the reward fees available for the claim for the account
    /// @param account to get the reward fees available for the claim for
    /// @return the rewards fees available for the claim for the account
    function getRewardFeesAvailable(address account) external view returns (uint) {
        return _calculateAvailableFeesToClaim(account);
    }

    /// @notice Get the total rewards claimed for the account until now
    /// @param account to get the total rewards claimed for
    /// @return the total rewards claimed for the account until now
    function getAlreadyClaimedRewards(address account) external view returns (uint) {
        return stakerLifetimeRewardsClaimed[account];
    }

    /// @notice Get the rewards funds available on the rewards pool
    /// @return the rewards funds available on the rewards pool
    function getContractRewardFunds() external view returns (uint) {
        return stakingToken.balanceOf(address(ThalesStakingRewardsPool));
    }

    /// @notice Get the fee funds available on the staking contract
    /// @return the fee funds available on the staking contract
    function getContractFeeFunds() external view returns (uint) {
        return feeToken.balanceOf(address(this));
    }

    /// @notice Set staking parametars
    /// @param _claimEnabled enable/disable claim rewards
    /// @param _distributeFeesEnabled enable/disable fees distribution
    /// @param _durationPeriod duration of the staking period
    /// @param _unstakeDurationPeriod duration of the unstaking cooldown period
    /// @param _mergeAccountEnabled enable/disable account merging
    /// @param _readOnlyMode enable/disable readonlymode
    /// @param _sendCCIPMessage enable/disable sending CCIP message
    function setStakingParameters(
        bool _claimEnabled,
        bool _distributeFeesEnabled,
        uint _durationPeriod,
        uint _unstakeDurationPeriod,
        bool _mergeAccountEnabled,
        bool _readOnlyMode,
        bool _sendCCIPMessage
    ) external onlyOwner {
        claimEnabled = _claimEnabled;
        distributeFeesEnabled = _distributeFeesEnabled;
        durationPeriod = _durationPeriod;
        unstakeDurationPeriod = _unstakeDurationPeriod;
        mergeAccountEnabled = _mergeAccountEnabled;
        readOnlyMode = _readOnlyMode;
        sendCCIPMessage = _sendCCIPMessage;
        emit StakingParametersChanged(
            _claimEnabled,
            _distributeFeesEnabled,
            _durationPeriod,
            _unstakeDurationPeriod,
            _mergeAccountEnabled,
            _readOnlyMode,
            _sendCCIPMessage
        );
    }

    /// @notice Set staking rewards parameters
    /// @param _fixedReward amount for weekly base rewards pool
    /// @param _extraReward amount for weekly bonus rewards pool
    /// @param _extraRewardsActive enable/disable bonus rewards
    function setStakingRewardsParameters(
        uint _fixedReward,
        uint _extraReward,
        bool _extraRewardsActive
    ) external onlyOwner {
        fixedPeriodReward = _fixedReward;
        periodExtraReward = _extraReward;
        extraRewardsActive = _extraRewardsActive;

        emit StakingRewardsParametersChanged(_fixedReward, _extraReward, _extraRewardsActive);
    }

    /// @notice Set contract addresses
    /// @param _thalesAMM address of Thales AMM contract
    /// @param _thalesRangedAMM address of Thales ranged AMM contract
    /// @param _sportsAMM address of sport markets AMM contract
    /// @param _priceFeed address of price feed contract
    /// @param _thalesStakingRewardsPool address of Thales staking rewards pool
    /// @param _addressResolver address of address resolver contract
    /// @param _stakingThalesBonusRewardsManager manager for TIP-135 gamification systme
    function setAddresses(
        address _thalesAMM,
        address _thalesRangedAMM,
        address _sportsAMM,
        address _priceFeed,
        address _thalesStakingRewardsPool,
        address _addressResolver,
        address _stakingThalesBonusRewardsManager
    ) external onlyOwner {
        thalesAMM = _thalesAMM;
        thalesRangedAMM = _thalesRangedAMM;
        sportsAMM = _sportsAMM;
        priceFeed = IPriceFeed(_priceFeed);
        ThalesStakingRewardsPool = IThalesStakingRewardsPool(_thalesStakingRewardsPool);
        addressResolver = IAddressResolver(_addressResolver);
        stakingThalesBonusRewardsManager = IStakingThalesBonusRewardsManager(_stakingThalesBonusRewardsManager);
        emit AddressesChanged(
            _thalesAMM,
            _thalesRangedAMM,
            _sportsAMM,
            _priceFeed,
            _thalesStakingRewardsPool,
            _addressResolver,
            _stakingThalesBonusRewardsManager
        );
    }

    /// @notice Set address of Escrow Thales contract
    /// @param _escrowThalesContract address of Escrow Thales contract
    function setEscrow(address _escrowThalesContract) external onlyOwner {
        if (address(iEscrowThales) != address(0)) {
            stakingToken.approve(address(iEscrowThales), 0);
        }
        iEscrowThales = IEscrowThales(_escrowThalesContract);
        stakingToken.approve(_escrowThalesContract, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
        emit EscrowChanged(_escrowThalesContract);
    }

    /// @notice add a sport vault address to count towards gamified staking volume
    /// @param _sportVault address to set
    /// @param value to set
    function setSupportedSportVault(address _sportVault, bool value) external onlyOwner {
        supportedSportVault[_sportVault] = value;
        emit SupportedSportVaultSet(_sportVault, value);
    }

    /// @notice add a amm vault address to count towards gamified staking volume
    /// @param _ammVault address to set
    /// @param value to set
    function setSupportedAMMVault(address _ammVault, bool value) external onlyOwner {
        supportedAMMVault[_ammVault] = value;
        emit SupportedAMMVaultSet(_ammVault, value);
    }

    /// @notice Set last period timestamp
    /// @param _lastPeriodTimestamp last period timestamp to be set
    function setLastPeriodTimestamp(uint _lastPeriodTimestamp) external onlyOwner {
        require(_lastPeriodTimestamp > (lastPeriodTimeStamp - 5 hours), "Too far back");
        lastPeriodTimeStamp = _lastPeriodTimestamp;
        emit LastPeriodTimestampSet(_lastPeriodTimestamp);
    }

    /// @notice Get the base reward amount available for the claim for the account
    /// @param account to get the base reward amount available for the claim for
    /// @return the base reward amount available for the claim for the account
    function getBaseReward(address account) public view returns (uint _baseRewards) {
        if (
            !((_lastStakingPeriod[account] == periodsOfStaking) ||
                (_stakedBalances[account] == 0) ||
                (_lastRewardsClaimedPeriod[account] == periodsOfStaking) ||
                (totalStakedLastPeriodEnd == 0))
        ) {
            _baseRewards = _stakedBalances[account]
                .add(iEscrowThales.getStakedEscrowedBalanceForRewards(account))
                .mul(currentPeriodRewards)
                .div(totalStakedLastPeriodEnd.add(totalEscrowedLastPeriodEnd));
        }
    }

    /// @notice [DEPRECATED maintained because of IStakingThales] Get the total protocol volume for the account
    /// @param account to get the total protocol volume for
    /// @return the total protocol volume for the account
    function getAMMVolume(address account) external view returns (uint) {
        return 0;
    }

    /// @notice Get the total bonus rewards for the account
    /// @param account to get the total bonus rewards for
    /// @return the total bonus rewards for the account
    function getTotalBonus(address account) public view returns (uint returnValue) {
        if (
            (address(stakingThalesBonusRewardsManager) != address(0)) && stakingThalesBonusRewardsManager.useNewBonusModel()
        ) {
            returnValue = periodExtraReward
                .mul(stakingThalesBonusRewardsManager.getUserRoundBonusShare(account, periodsOfStaking - 1))
                .div(ONE);
        }
    }

    /// @notice Get the flag that indicates whether the current period can be closed
    /// @return the flag that indicates whether the current period can be closed
    function canClosePeriod() external view returns (bool) {
        return (startTimeStamp > 0 && (block.timestamp >= lastPeriodTimeStamp.add(durationPeriod)));
    }

    /* ========== PUBLIC ========== */

    /// @notice Start the first staking period
    function startStakingPeriod() external onlyOwner {
        require(startTimeStamp == 0, "Staking has already started");
        startTimeStamp = block.timestamp;
        periodsOfStaking = 0;
        lastPeriodTimeStamp = startTimeStamp;
        _totalRewardsClaimed = 0;
        _totalRewardFeesClaimed = 0;
        _totalStakedAmount = 0;
        _totalEscrowedAmount = 0;
        _totalPendingStakeAmount = 0;
        emit StakingPeriodStarted();
    }

    /// @notice Close the current staking period
    function closePeriod() external nonReentrant notPaused {
        require(startTimeStamp > 0, "Staking period has not started");
        require(
            block.timestamp >= lastPeriodTimeStamp.add(durationPeriod),
            "A full period has not passed since the last closed period"
        );
        require(!closingPeriodInProgress, "ClosingInProgress");
        iEscrowThales.updateCurrentPeriod();
        lastPeriodTimeStamp = block.timestamp;
        periodsOfStaking = iEscrowThales.currentVestingPeriod();

        totalEscrowedLastPeriodEnd = iEscrowThales.totalEscrowedRewards().sub(
            iEscrowThales.totalEscrowBalanceNotIncludedInStaking()
        );

        currentPeriodRewards = fixedPeriodReward;
        currentPeriodFees = feeToken.balanceOf(address(this));
        totalStakedLastPeriodEnd = _totalStakedAmount;

        if (sendCCIPMessage) {
            _sendRoundClosingMessageCrosschain();
        }
        emit ClosedPeriod(periodsOfStaking, lastPeriodTimeStamp);
    }

    /// @notice if CCIP is configured, this method will send the staking data to relevant chains
    function sendRoundClosingMessageCrosschain() external onlyOwner {
        _sendRoundClosingMessageCrosschain();
    }

    function _sendRoundClosingMessageCrosschain() internal {
        if (addressResolver.checkIfContractExists("CrossChainCollector")) {
            if (!readOnlyMode) {
                paused = true;
                closingPeriodInProgress = true;
                lastPauseTime = block.timestamp;
                closingPeriodPauseTime = block.timestamp;
            }
            ICCIPCollector(addressResolver.getAddress("CrossChainCollector")).sendOnClosePeriod(
                totalStakedLastPeriodEnd,
                totalEscrowedLastPeriodEnd,
                stakingThalesBonusRewardsManager.totalRoundBonusPoints(periodsOfStaking - 1),
                _reverseTransformCollateral(feeToken.balanceOf(address(this)))
            );
        }
    }

    /// @notice Updating the staking rewards parameters after closed period with the calculated values via CCIP
    /// @param _currentPeriodRewards the calculated base rewards to be distributed for the current period on the particular chain
    /// @param _extraRewards the calculated extra rewards to be distributed for the current period on the particular chain
    /// @param _revShare the calculated revenue share to be distributed for the current period on the particular chain
    function updateStakingRewards(
        uint _currentPeriodRewards,
        uint _extraRewards,
        uint _revShare
    ) external nonReentrant {
        if (!readOnlyMode) {
            // if it is readOnlyMode==true  discard all following the updates
            require(msg.sender == addressResolver.getAddress("CrossChainCollector") || msg.sender == owner, "InvCCIP");
            require(closingPeriodInProgress, "NotInClosePeriod");

            require(
                _currentPeriodRewards <= fixedPeriodReward &&
                    _extraRewards <= fixedPeriodReward &&
                    _revShare <= 5 * fixedPeriodReward,
                "Rejected due to suspicious values"
            );

            bool safeBoxBufferSet = addressResolver.checkIfContractExists("SafeBoxBuffer");
            bool insufficientFundsInBuffer;

            uint currentBalance = feeToken.balanceOf(address(this));
            currentPeriodFees = _transformCollateral(_revShare);

            if (safeBoxBufferSet) {
                address safeBoxBuffer = addressResolver.getAddress("SafeBoxBuffer");
                if (currentPeriodFees > currentBalance) {
                    if (feeToken.balanceOf(safeBoxBuffer) < (currentPeriodFees - currentBalance)) {
                        insufficientFundsInBuffer = true;
                    } else {
                        ICCIPCollector(safeBoxBuffer).pullExtraFunds(currentPeriodFees - currentBalance);
                    }
                } else if (currentPeriodFees > 0 && currentPeriodFees < currentBalance) {
                    feeToken.transfer(safeBoxBuffer, currentBalance - currentPeriodFees);
                }
            }
            currentPeriodRewards = _currentPeriodRewards;
            periodExtraReward = _extraRewards;
            closingPeriodInProgress = false;
            if (closingPeriodPauseTime == lastPauseTime) {
                paused = !safeBoxBufferSet || insufficientFundsInBuffer;
            }
        }
        emit ReceivedStakingRewardsUpdate(_currentPeriodRewards, _extraRewards, _transformCollateral(_revShare));
    }

    /// @notice Stake the amount of staking token to get weekly rewards
    /// @param amount to stake
    function stake(uint amount) external nonReentrant notPaused {
        _stake(amount, msg.sender, msg.sender);
        emit Staked(msg.sender, amount);
    }

    /// @notice Start unstaking cooldown for the amount of staking token
    /// @param amount to unstake
    function startUnstake(uint amount) external notPaused {
        require(amount > 0, "Cannot unstake 0");
        require(_stakedBalances[msg.sender] >= amount, "Account doesnt have that much staked");
        require(!unstaking[msg.sender], "Account has already triggered unstake cooldown");

        if (_calculateAvailableRewardsToClaim(msg.sender) > 0) {
            _claimReward(msg.sender);
        }
        lastUnstakeTime[msg.sender] = block.timestamp;
        unstaking[msg.sender] = true;
        _totalStakedAmount = _totalStakedAmount.sub(amount);
        unstakingAmount[msg.sender] = amount;
        _stakedBalances[msg.sender] = _stakedBalances[msg.sender].sub(amount);

        // on full unstake add his escrowed balance to totalEscrowBalanceNotIncludedInStaking
        if (_stakedBalances[msg.sender] == 0) {
            if (iEscrowThales.totalAccountEscrowedAmount(msg.sender) > 0) {
                iEscrowThales.addTotalEscrowBalanceNotIncludedInStaking(
                    iEscrowThales.totalAccountEscrowedAmount(msg.sender)
                );
            }
        }

        emit UnstakeCooldown(msg.sender, lastUnstakeTime[msg.sender].add(unstakeDurationPeriod), amount);
    }

    /// @notice Cancel unstaking cooldown
    function cancelUnstake() external notPaused {
        require(unstaking[msg.sender], "Account is not unstaking");

        // on revert full unstake remove his escrowed balance from totalEscrowBalanceNotIncludedInStaking
        _subtractTotalEscrowBalanceNotIncludedInStaking(msg.sender);

        if (_calculateAvailableRewardsToClaim(msg.sender) > 0) {
            _claimReward(msg.sender);
        }

        unstaking[msg.sender] = false;
        _totalStakedAmount = _totalStakedAmount.add(unstakingAmount[msg.sender]);
        _stakedBalances[msg.sender] = _stakedBalances[msg.sender].add(unstakingAmount[msg.sender]);
        unstakingAmount[msg.sender] = 0;

        emit CancelUnstake(msg.sender);
    }

    /// @notice Unstake after the cooldown period expired
    function unstake() external notPaused {
        require(unstaking[msg.sender], "Account has not triggered unstake cooldown");
        require(
            lastUnstakeTime[msg.sender] < block.timestamp.sub(unstakeDurationPeriod),
            "Cannot unstake yet, cooldown not expired."
        );
        unstaking[msg.sender] = false;
        uint unstakeAmount = unstakingAmount[msg.sender];
        stakingToken.safeTransfer(msg.sender, unstakeAmount);
        unstakingAmount[msg.sender] = 0;
        emit Unstaked(msg.sender, unstakeAmount);
    }

    /// @notice Claim the weekly staking rewards
    function claimReward() public nonReentrant notPaused {
        _claimReward(msg.sender);
    }

    /// @notice Claim the weekly staking rewards on behalf of the account
    /// @param account to claim on behalf of
    function claimRewardOnBehalf(address account) public nonReentrant notPaused {
        require(account != address(0) && account != msg.sender, "Invalid address");
        require(canClaimOnBehalf[account][msg.sender], "Cannot claim on behalf");
        _claimReward(account);
    }

    /// @notice Update the protocol volume for the account
    /// @param account to update the protocol volume for
    /// @param amount to add to the existing protocol volume
    function updateVolume(address account, uint amount) external {
        require(account != address(0) && amount > 0, "Invalid params");
        if (delegatedVolume[account] != address(0)) {
            account = delegatedVolume[account];
        }

        require(
            msg.sender == thalesAMM ||
                msg.sender == thalesRangedAMM ||
                msg.sender == sportsAMM ||
                supportedSportVault[msg.sender] ||
                supportedAMMVault[msg.sender],
            "Invalid address"
        );
        amount = _reverseTransformCollateral(amount);
        if (address(stakingThalesBonusRewardsManager) != address(0)) {
            stakingThalesBonusRewardsManager.storePoints(account, msg.sender, amount, periodsOfStaking);
        }

        emit AMMVolumeUpdated(account, amount, msg.sender);
    }

    /// @notice Merge account to transfer all staking amounts to another account
    /// @param destAccount to merge into
    function mergeAccount(address destAccount) external notPaused {
        require(mergeAccountEnabled, "Merge account is disabled");
        require(destAccount != address(0) && destAccount != msg.sender, "Invalid address");
        require(
            _calculateAvailableRewardsToClaim(msg.sender) == 0 && _calculateAvailableRewardsToClaim(destAccount) == 0,
            "Cannot merge, claim rewards on both accounts before merging"
        );
        require(
            !unstaking[msg.sender] && !unstaking[destAccount],
            "Cannot merge, cancel unstaking on both accounts before merging"
        );

        iEscrowThales.mergeAccount(msg.sender, destAccount);

        _stakedBalances[destAccount] = _stakedBalances[destAccount].add(_stakedBalances[msg.sender]);
        stakerLifetimeRewardsClaimed[destAccount] = stakerLifetimeRewardsClaimed[destAccount].add(
            stakerLifetimeRewardsClaimed[msg.sender]
        );
        stakerFeesClaimed[destAccount] = stakerFeesClaimed[destAccount].add(stakerFeesClaimed[msg.sender]);

        _lastRewardsClaimedPeriod[destAccount] = periodsOfStaking;
        _lastStakingPeriod[destAccount] = periodsOfStaking;
        delete lastUnstakeTime[msg.sender];
        delete unstaking[msg.sender];
        delete unstakingAmount[msg.sender];
        delete _stakedBalances[msg.sender];
        delete stakerLifetimeRewardsClaimed[msg.sender];
        delete stakerFeesClaimed[msg.sender];
        delete _lastRewardsClaimedPeriod[msg.sender];
        delete _lastStakingPeriod[msg.sender];

        emit AccountMerged(msg.sender, destAccount);
    }

    /// @notice Set flag to enable/disable claim on behalf of the msg.sender for the account
    /// @param account to enable/disable claim on behalf of msg.sender
    /// @param _canClaimOnBehalf enable/disable claim on behalf of the msg.sender for the account
    function setCanClaimOnBehalf(address account, bool _canClaimOnBehalf) external notPaused {
        require(account != address(0) && account != msg.sender, "Invalid address");
        canClaimOnBehalf[msg.sender][account] = _canClaimOnBehalf;
        emit CanClaimOnBehalfChanged(msg.sender, account, _canClaimOnBehalf);
    }

    /// @notice delegate your volume to another address
    /// @param account address to delegate to
    function delegateVolume(address account) external notPaused {
        delegatedVolume[msg.sender] = account;
        emit DelegatedVolume(account);
    }

    /* ========== INTERNAL FUNCTIONS ========== */

    function _claimReward(address account) internal notPaused {
        require(claimEnabled, "Claiming is not enabled.");
        require(startTimeStamp > 0, "Staking period has not started");
        require(_lastRewardsClaimedPeriod[account] < periodsOfStaking, "Already claimed");
        
        //Calculate rewards
        if (distributeFeesEnabled) {
            uint availableFeesToClaim = _calculateAvailableFeesToClaim(account);
            if (availableFeesToClaim > 0) {
                feeToken.safeTransfer(account, availableFeesToClaim);
                stakerFeesClaimed[account] = stakerFeesClaimed[account].add(availableFeesToClaim);
                _totalRewardFeesClaimed = _totalRewardFeesClaimed.add(availableFeesToClaim);
                emit FeeRewardsClaimed(account, availableFeesToClaim);
            }
        }
        uint availableRewardsToClaim = _calculateAvailableRewardsToClaim(account);
        if (availableRewardsToClaim > 0) {
            // Transfer THALES to Escrow contract
            ThalesStakingRewardsPool.addToEscrow(account, availableRewardsToClaim);
            // Record the total claimed rewards
            stakerLifetimeRewardsClaimed[account] = stakerLifetimeRewardsClaimed[account].add(availableRewardsToClaim);
            _totalRewardsClaimed = _totalRewardsClaimed.add(availableRewardsToClaim);

            emit RewardsClaimed(account, availableRewardsToClaim, getBaseReward(account));
        }
        // Update last claiming period
        _lastRewardsClaimedPeriod[account] = periodsOfStaking;
    }

    function _stake(
        uint amount,
        address staker,
        address sender
    ) internal {
        require(startTimeStamp > 0, "Staking period has not started");
        require(amount > 0, "Cannot stake 0");
        require(!unstaking[staker], "The staker is paused from staking due to unstaking");
        // Check if there are not claimable rewards from last period.
        // Claim them, and add new stake
        if (_calculateAvailableRewardsToClaim(staker) > 0) {
            _claimReward(staker);
        }
        _lastStakingPeriod[staker] = periodsOfStaking;

        // if just started staking subtract his escrowed balance from totalEscrowBalanceNotIncludedInStaking
        _subtractTotalEscrowBalanceNotIncludedInStaking(staker);

        _totalStakedAmount = _totalStakedAmount.add(amount);
        _stakedBalances[staker] = _stakedBalances[staker].add(amount);
        stakingToken.safeTransferFrom(sender, address(this), amount);
    }

    function _subtractTotalEscrowBalanceNotIncludedInStaking(address account) internal {
        if (_stakedBalances[account] == 0) {
            if (iEscrowThales.totalAccountEscrowedAmount(account) > 0) {
                iEscrowThales.subtractTotalEscrowBalanceNotIncludedInStaking(
                    iEscrowThales.totalAccountEscrowedAmount(account)
                );
            }
        }
    }

    function _calculateAvailableRewardsToClaim(address account) internal view returns (uint) {
        uint baseReward = getBaseReward(account);
        if (baseReward == 0) {
            return 0;
        }
        if (!extraRewardsActive) {
            return baseReward;
        } else {
            return baseReward.add(getTotalBonus(account));
        }
    }

    function _calculateAvailableFeesToClaim(address account) internal view returns (uint) {
        uint baseReward = getBaseReward(account);
        if (baseReward == 0) {
            return 0;
        }

        return
            _stakedBalances[account]
                .add(iEscrowThales.getStakedEscrowedBalanceForRewards(account))
                .mul(currentPeriodFees)
                .div(totalStakedLastPeriodEnd.add(totalEscrowedLastPeriodEnd));
    }

    function _transformCollateral(uint _amount) internal view returns (uint) {
        return (ICCIPCollector(address(feeToken)).decimals() == 6) ? _amount / 1e12 : _amount;
    }

    function _reverseTransformCollateral(uint _amount) internal view returns (uint) {
        return (ICCIPCollector(address(feeToken)).decimals() == 6) ? _amount * 1e12 : _amount;
    }

    /* ========== EVENTS ========== */

    event RewardAdded(uint reward);
    event Staked(address user, uint amount);
    event StakedOnBehalf(address user, address staker, uint amount);
    event ClosedPeriod(uint PeriodOfStaking, uint lastPeriodTimeStamp);
    event RewardsClaimed(address account, uint unclaimedReward, uint baseRewards);
    event FeeRewardsClaimed(address account, uint unclaimedFees);
    event UnstakeCooldown(address account, uint cooldownTime, uint amount);
    event CancelUnstake(address account);
    event Unstaked(address account, uint unstakeAmount);
    event StakingParametersChanged(
        bool claimEnabled,
        bool distributeFeesEnabled,
        uint durationPeriod,
        uint unstakeDurationPeriod,
        bool mergeAccountEnabled,
        bool readOnlyMode,
        bool sendCCIPMessage
    );
    event StakingRewardsParametersChanged(uint fixedPeriodReward, uint periodExtraReward, bool extraRewardsActive);
    event AddressesChanged(
        address thalesAMM,
        address thalesRangedAMM,
        address sportsAMM,
        address priceFeed,
        address ThalesStakingRewardsPool,
        address addressResolver,
        address stakingThalesBonusRewardsManager
    );
    event ReceivedStakingRewardsUpdate(uint _currentPeriodRewards, uint _extraRewards, uint _revShare);
    event EscrowChanged(address newEscrow);
    event StakingPeriodStarted();
    event AMMVolumeUpdated(address account, uint amount, address source);
    event AccountMerged(address srcAccount, address destAccount);
    event DelegatedVolume(address destAccount);
    event CanClaimOnBehalfChanged(address sender, address account, bool canClaimOnBehalf);
    event SupportedAMMVaultSet(address vault, bool value);
    event SupportedSportVaultSet(address vault, bool value);
    event LastPeriodTimestampSet(uint lastPeriodTimestamp);
}

File 2 of 26 : SafeERC20.sol
pragma solidity ^0.5.0;

import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using SafeMath for uint256;
    using Address for address;

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

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

    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        // solhint-disable-next-line max-line-length
        require((value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

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

    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).sub(value);
        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves.

        // A Solidity high level call has three parts:
        //  1. The target address is checked to verify it contains contract code
        //  2. The call itself is made, and success asserted
        //  3. The return value is decoded, which in turn checks the size of the returned data.
        // solhint-disable-next-line max-line-length
        require(address(token).isContract(), "SafeERC20: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = address(token).call(data);
        require(success, "SafeERC20: low-level call failed");

        if (returndata.length > 0) { // Return data is optional
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

File 3 of 26 : SafeMath.sol
pragma solidity ^0.5.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, 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");
        uint256 c = a - b;

        return c;
    }

    /**
     * @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) {
        // 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-solidity/pull/522
        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. Reverts 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) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, "SafeMath: division by zero");
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts 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;
    }
}

File 4 of 26 : ProxyReentrancyGuard.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.5.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the `nonReentrant` modifier
 * available, which can be aplied 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.
 */
contract ProxyReentrancyGuard {
    /// @dev counter to allow mutex lock with only one SSTORE operation
    uint256 private _guardCounter;
    bool private _initialized;

    function initNonReentrant() public {
        require(!_initialized, "Already initialized");
        _initialized = true;
        _guardCounter = 1;
    }

    /**
     * @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() {
        _guardCounter += 1;
        uint256 localCounter = _guardCounter;
        _;
        require(localCounter == _guardCounter, "ReentrancyGuard: reentrant call");
    }
}

File 5 of 26 : ProxyOwned.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.5.16;

// Clone of syntetix contract without constructor
contract ProxyOwned {
    address public owner;
    address public nominatedOwner;
    bool private _initialized;
    bool private _transferredAtInit;

    function setOwner(address _owner) public {
        require(_owner != address(0), "Owner address cannot be 0");
        require(!_initialized, "Already initialized, use nominateNewOwner");
        _initialized = true;
        owner = _owner;
        emit OwnerChanged(address(0), _owner);
    }

    function nominateNewOwner(address _owner) external onlyOwner {
        nominatedOwner = _owner;
        emit OwnerNominated(_owner);
    }

    function acceptOwnership() external {
        require(msg.sender == nominatedOwner, "You must be nominated before you can accept ownership");
        emit OwnerChanged(owner, nominatedOwner);
        owner = nominatedOwner;
        nominatedOwner = address(0);
    }

    function transferOwnershipAtInit(address proxyAddress) external onlyOwner {
        require(proxyAddress != address(0), "Invalid address");
        require(!_transferredAtInit, "Already transferred");
        owner = proxyAddress;
        _transferredAtInit = true;
        emit OwnerChanged(owner, proxyAddress);
    }

    modifier onlyOwner {
        _onlyOwner();
        _;
    }

    function _onlyOwner() private view {
        require(msg.sender == owner, "Only the contract owner may perform this action");
    }

    event OwnerNominated(address newOwner);
    event OwnerChanged(address oldOwner, address newOwner);
}

File 6 of 26 : ProxyPausable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.5.16;

// Inheritance
import "./ProxyOwned.sol";

// Clone of syntetix contract without constructor

contract ProxyPausable is ProxyOwned {
    uint public lastPauseTime;
    bool public paused;

    

    /**
     * @notice Change the paused state of the contract
     * @dev Only the contract owner may call this.
     */
    function setPaused(bool _paused) external onlyOwner {
        // Ensure we're actually changing the state before we do anything
        if (_paused == paused) {
            return;
        }

        // Set our paused state.
        paused = _paused;

        // If applicable, set the last pause time.
        if (paused) {
            lastPauseTime = block.timestamp;
        }

        // Let everyone know that our pause state has changed.
        emit PauseChanged(paused);
    }

    event PauseChanged(bool isPaused);

    modifier notPaused {
        require(!paused, "This action cannot be performed while the contract is paused");
        _;
    }
}

File 7 of 26 : Initializable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.4.24 <0.7.0;


/**
 * @title Initializable
 *
 * @dev Helper contract to support initializer functions. To use it, replace
 * the constructor with a function that has the `initializer` modifier.
 * WARNING: Unlike constructors, initializer functions must be manually
 * invoked. This applies both to deploying an Initializable contract, as well
 * as extending an Initializable contract via inheritance.
 * WARNING: When used with inheritance, manual care must be taken to not invoke
 * a parent initializer twice, or ensure that all initializers are idempotent,
 * because this is not dealt with automatically as with constructors.
 */
contract Initializable {

  /**
   * @dev Indicates that the contract has been initialized.
   */
  bool private initialized;

  /**
   * @dev Indicates that the contract is in the process of being initialized.
   */
  bool private initializing;

  /**
   * @dev Modifier to use in the initializer function of a contract.
   */
  modifier initializer() {
    require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized");

    bool isTopLevelCall = !initializing;
    if (isTopLevelCall) {
      initializing = true;
      initialized = true;
    }

    _;

    if (isTopLevelCall) {
      initializing = false;
    }
  }

  /// @dev Returns true if and only if the function is running in the constructor
  function isConstructor() private view returns (bool) {
    // extcodesize checks the size of the code stored in an address, and
    // address returns the current address. Since the code is still not
    // deployed when running a constructor, any checks on its code size will
    // yield zero, making it an effective way to detect if a contract is
    // under construction or not.
    address self = address(this);
    uint256 cs;
    assembly { cs := extcodesize(self) }
    return cs == 0;
  }

  // Reserved storage space to allow for layout changes in the future.
  uint256[50] private ______gap;
}

File 8 of 26 : IEscrowThales.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.5.16;

interface IEscrowThales {
    /* ========== VIEWS / VARIABLES ========== */
    function getStakerPeriod(address account, uint index) external view returns (uint);

    function getStakerAmounts(address account, uint index) external view returns (uint);

    function totalAccountEscrowedAmount(address account) external view returns (uint);

    function getStakedEscrowedBalanceForRewards(address account) external view returns (uint);

    function totalEscrowedRewards() external view returns (uint);

    function totalEscrowBalanceNotIncludedInStaking() external view returns (uint);

    function currentVestingPeriod() external view returns (uint);

    function updateCurrentPeriod() external returns (bool);

    function claimable(address account) external view returns (uint);

    function addToEscrow(address account, uint amount) external;

    function vest(uint amount) external returns (bool);

    function addTotalEscrowBalanceNotIncludedInStaking(uint amount) external;

    function subtractTotalEscrowBalanceNotIncludedInStaking(uint amount) external;

    function mergeAccount(address srcAccount, address destAccount) external;
}

File 9 of 26 : IStakingThales.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.5.16;

interface IStakingThales {
    function updateVolume(address account, uint amount) external;

    function updateStakingRewards(
        uint _currentPeriodRewards,
        uint _extraRewards,
        uint _revShare
    ) external;

    /* ========== VIEWS / VARIABLES ==========  */
    function totalStakedAmount() external view returns (uint);

    function stakedBalanceOf(address account) external view returns (uint);

    function currentPeriodRewards() external view returns (uint);

    function currentPeriodFees() external view returns (uint);

    function getLastPeriodOfClaimedRewards(address account) external view returns (uint);

    function getRewardsAvailable(address account) external view returns (uint);

    function getRewardFeesAvailable(address account) external view returns (uint);

    function getAlreadyClaimedRewards(address account) external view returns (uint);

    function getContractRewardFunds() external view returns (uint);

    function getContractFeeFunds() external view returns (uint);

    function getAMMVolume(address account) external view returns (uint);
}

File 10 of 26 : ISNXRewards.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.5.16;

interface ISNXRewards {
    /* ========== VIEWS / VARIABLES ========== */
    function collateralisationRatioAndAnyRatesInvalid(address account) external view returns (uint, bool);

    function debtBalanceOf(address _issuer, bytes32 currencyKey) external view returns (uint);

    function issuanceRatio() external view returns (uint);

    function setCRatio(address account, uint _c_ratio) external;

    function setIssuanceRatio(uint _issuanceRation) external;
}

File 11 of 26 : IThalesRoyale.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.5.16;
pragma experimental ABIEncoderV2;
import "../interfaces/IPassportPosition.sol";

interface IThalesRoyale {
    /* ========== VIEWS / VARIABLES ========== */
    function getBuyInAmount() external view returns (uint);

    function season() external view returns (uint);

    function tokenSeason(uint tokenId) external view returns (uint);

    function seasonFinished(uint _season) external view returns (bool);

    function roundInASeason(uint _round) external view returns (uint);

    function roundResultPerSeason(uint _season, uint round) external view returns (uint);

    function isTokenAliveInASpecificSeason(uint tokenId, uint _season) external view returns (bool);

    function hasParticipatedInCurrentOrLastRoyale(address _player) external view returns (bool);

    function getTokenPositions(uint tokenId) external view returns (IPassportPosition.Position[] memory);
}

File 12 of 26 : IPriceFeed.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.5.16;

interface IPriceFeed {
    // Structs
    struct RateAndUpdatedTime {
        uint216 rate;
        uint40 time;
    }

    // Mutative functions
    function addAggregator(bytes32 currencyKey, address aggregatorAddress) external;

    function removeAggregator(bytes32 currencyKey) external;

    // Views

    function rateForCurrency(bytes32 currencyKey) external view returns (uint);

    function rateAndUpdatedTime(bytes32 currencyKey) external view returns (uint rate, uint time);

    function getRates() external view returns (uint[] memory);

    function getCurrencies() external view returns (bytes32[] memory);
}

File 13 of 26 : IThalesStakingRewardsPool.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.5.16;

interface IThalesStakingRewardsPool {
    function addToEscrow(address account, uint amount) external;
}

File 14 of 26 : IAddressResolver.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.5.16;

// pragma experimental ABIEncoderV2;

interface IAddressResolver {
    /* ========== VIEWS / VARIABLES ========== */
    // function getAddress(bytes32 _contractName) external view returns (address contract_);

    // function getAddresses(string[] calldata _contractNames) external view returns (address[] memory contracts);

    function getAddress(string calldata _contractName) external view returns (address contract_);

    function checkIfContractExists(string calldata _contractName) external view returns (bool contractExists);
}

File 15 of 26 : ISportsAMMLiquidityPool.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.5.16;

interface ISportsAMMLiquidityPool {
    /* ========== VIEWS / VARIABLES ========== */

    function isUserLPing(address user) external view returns (bool isUserInLP);
}

File 16 of 26 : IThalesAMMLiquidityPool.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.5.16;

interface IThalesAMMLiquidityPool {
    /* ========== VIEWS / VARIABLES ========== */

    function isUserLPing(address user) external view returns (bool isUserInLP);
}

File 17 of 26 : IParlayAMMLiquidityPool.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.5.16;

interface IParlayAMMLiquidityPool {
    function commitTrade(address market, uint amountToMint) external;

    function getMarketRound(address market) external view returns (uint _round);

    function getMarketPool(address market) external view returns (address roundPool);

    function transferToPool(address market, uint amount) external;

    function isUserLPing(address user) external view returns (bool isUserInLP);
}

File 18 of 26 : IThalesAMM.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.5.16;

import "./IPriceFeed.sol";

interface IThalesAMM {
    enum Position {
        Up,
        Down
    }

    function manager() external view returns (address);

    function availableToBuyFromAMM(address market, Position position) external view returns (uint);

    function impliedVolatilityPerAsset(bytes32 oracleKey) external view returns (uint);

    function buyFromAmmQuote(
        address market,
        Position position,
        uint amount
    ) external view returns (uint);

    function buyFromAMM(
        address market,
        Position position,
        uint amount,
        uint expectedPayout,
        uint additionalSlippage
    ) external returns (uint);

    function availableToSellToAMM(address market, Position position) external view returns (uint);

    function sellToAmmQuote(
        address market,
        Position position,
        uint amount
    ) external view returns (uint);

    function sellToAMM(
        address market,
        Position position,
        uint amount,
        uint expectedPayout,
        uint additionalSlippage
    ) external returns (uint);

    function isMarketInAMMTrading(address market) external view returns (bool);

    function price(address market, Position position) external view returns (uint);

    function buyPriceImpact(
        address market,
        Position position,
        uint amount
    ) external view returns (int);

    function sellPriceImpact(
        address market,
        Position position,
        uint amount
    ) external view returns (int);

    function priceFeed() external view returns (IPriceFeed);
}

File 19 of 26 : IPositionalMarketManager.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.5.16;

import "../interfaces/IPositionalMarket.sol";

interface IPositionalMarketManager {
    /* ========== VIEWS / VARIABLES ========== */

    function durations() external view returns (uint expiryDuration, uint maxTimeToMaturity);

    function capitalRequirement() external view returns (uint);

    function marketCreationEnabled() external view returns (bool);

    function onlyAMMMintingAndBurning() external view returns (bool);

    function transformCollateral(uint value) external view returns (uint);

    function reverseTransformCollateral(uint value) external view returns (uint);

    function totalDeposited() external view returns (uint);

    function numActiveMarkets() external view returns (uint);

    function activeMarkets(uint index, uint pageSize) external view returns (address[] memory);

    function numMaturedMarkets() external view returns (uint);

    function maturedMarkets(uint index, uint pageSize) external view returns (address[] memory);

    function isActiveMarket(address candidate) external view returns (bool);

    function isKnownMarket(address candidate) external view returns (bool);

    function getThalesAMM() external view returns (address);

    /* ========== MUTATIVE FUNCTIONS ========== */

    function createMarket(
        bytes32 oracleKey,
        uint strikePrice,
        uint maturity,
        uint initialMint // initial sUSD to mint options for,
    ) external returns (IPositionalMarket);

    function resolveMarket(address market) external;

    function expireMarkets(address[] calldata market) external;

    function transferSusdTo(
        address sender,
        address receiver,
        uint amount
    ) external;
}

File 20 of 26 : IStakingThalesBonusRewardsManager.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.5.16;

interface IStakingThalesBonusRewardsManager {
    function storePoints(
        address user,
        address origin,
        uint basePoins,
        uint round
    ) external;

    function getUserRoundBonusShare(address user, uint round) external view returns (uint);

    function useNewBonusModel() external view returns (bool);

    function totalRoundBonusPoints(uint round) external view returns (uint);
}

File 21 of 26 : ICCIPCollector.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.5.16;

interface ICCIPCollector {
    function sendOnClosePeriod(
        uint _totalStakedLastPeriodEnd,
        uint _totalEscrowedLastPeriodEnd,
        uint _totalBonusPointsInRound,
        uint _revShare
    ) external;

    function pullExtraFunds(uint _amount) external;

    function decimals() external view returns (uint);
}

File 22 of 26 : IERC20.sol
pragma solidity ^0.5.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP. Does not include
 * the optional functions; to access them see `ERC20Detailed`.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

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

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

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

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

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

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

File 23 of 26 : Address.sol
pragma solidity ^0.5.0;

/**
 * @dev Collection of functions related to the address type,
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * This test is non-exhaustive, and there may be false-negatives: during the
     * execution of a contract's constructor, its address will be reported as
     * not containing a contract.
     *
     * > It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies in extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

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

File 24 of 26 : IPassportPosition.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.5.16;

interface IPassportPosition {
    struct Position {
        uint round;
        uint position;
    }
}

File 25 of 26 : IPositionalMarket.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.5.16;

import "../interfaces/IPositionalMarketManager.sol";
import "../interfaces/IPosition.sol";
import "../interfaces/IPriceFeed.sol";

interface IPositionalMarket {
    /* ========== TYPES ========== */

    enum Phase {
        Trading,
        Maturity,
        Expiry
    }
    enum Side {
        Up,
        Down
    }

    /* ========== VIEWS / VARIABLES ========== */

    function getOptions() external view returns (IPosition up, IPosition down);

    function times() external view returns (uint maturity, uint destructino);

    function getOracleDetails()
        external
        view
        returns (
            bytes32 key,
            uint strikePrice,
            uint finalPrice
        );

    function fees() external view returns (uint poolFee, uint creatorFee);

    function deposited() external view returns (uint);

    function creator() external view returns (address);

    function resolved() external view returns (bool);

    function phase() external view returns (Phase);

    function oraclePrice() external view returns (uint);

    function oraclePriceAndTimestamp() external view returns (uint price, uint updatedAt);

    function canResolve() external view returns (bool);

    function result() external view returns (Side);

    function balancesOf(address account) external view returns (uint up, uint down);

    function totalSupplies() external view returns (uint up, uint down);

    function getMaximumBurnable(address account) external view returns (uint amount);

    /* ========== MUTATIVE FUNCTIONS ========== */

    function mint(uint value) external;

    function exerciseOptions() external returns (uint);

    function burnOptions(uint amount) external;

    function burnOptionsMaximum() external;
}

File 26 of 26 : IPosition.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.5.16;

import "./IPositionalMarket.sol";

interface IPosition {
    /* ========== VIEWS / VARIABLES ========== */

    function getBalanceOf(address account) external view returns (uint);

    function getTotalSupply() external view returns (uint);

    function exerciseWithAmount(address claimant, uint amount) external;
}

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

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"source","type":"address"}],"name":"AMMVolumeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"srcAccount","type":"address"},{"indexed":false,"internalType":"address","name":"destAccount","type":"address"}],"name":"AccountMerged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"thalesAMM","type":"address"},{"indexed":false,"internalType":"address","name":"thalesRangedAMM","type":"address"},{"indexed":false,"internalType":"address","name":"sportsAMM","type":"address"},{"indexed":false,"internalType":"address","name":"priceFeed","type":"address"},{"indexed":false,"internalType":"address","name":"ThalesStakingRewardsPool","type":"address"},{"indexed":false,"internalType":"address","name":"addressResolver","type":"address"},{"indexed":false,"internalType":"address","name":"stakingThalesBonusRewardsManager","type":"address"}],"name":"AddressesChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"canClaimOnBehalf","type":"bool"}],"name":"CanClaimOnBehalfChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"CancelUnstake","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"PeriodOfStaking","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lastPeriodTimeStamp","type":"uint256"}],"name":"ClosedPeriod","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"destAccount","type":"address"}],"name":"DelegatedVolume","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newEscrow","type":"address"}],"name":"EscrowChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"unclaimedFees","type":"uint256"}],"name":"FeeRewardsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"lastPeriodTimestamp","type":"uint256"}],"name":"LastPeriodTimestampSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isPaused","type":"bool"}],"name":"PauseChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_currentPeriodRewards","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_extraRewards","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_revShare","type":"uint256"}],"name":"ReceivedStakingRewardsUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"RewardAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"unclaimedReward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"baseRewards","type":"uint256"}],"name":"RewardsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"StakedOnBehalf","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"claimEnabled","type":"bool"},{"indexed":false,"internalType":"bool","name":"distributeFeesEnabled","type":"bool"},{"indexed":false,"internalType":"uint256","name":"durationPeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unstakeDurationPeriod","type":"uint256"},{"indexed":false,"internalType":"bool","name":"mergeAccountEnabled","type":"bool"},{"indexed":false,"internalType":"bool","name":"readOnlyMode","type":"bool"},{"indexed":false,"internalType":"bool","name":"sendCCIPMessage","type":"bool"}],"name":"StakingParametersChanged","type":"event"},{"anonymous":false,"inputs":[],"name":"StakingPeriodStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"fixedPeriodReward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"periodExtraReward","type":"uint256"},{"indexed":false,"internalType":"bool","name":"extraRewardsActive","type":"bool"}],"name":"StakingRewardsParametersChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"bool","name":"value","type":"bool"}],"name":"SupportedAMMVaultSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"bool","name":"value","type":"bool"}],"name":"SupportedSportVaultSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"cooldownTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"UnstakeCooldown","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"unstakeAmount","type":"uint256"}],"name":"Unstaked","type":"event"},{"constant":true,"inputs":[],"name":"ThalesStakingRewardsPool","outputs":[{"internalType":"contract IThalesStakingRewardsPool","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"canClaimOnBehalf","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"canClosePeriod","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"cancelUnstake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"claimEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"claimReward","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"claimRewardOnBehalf","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"closePeriod","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"closingPeriodInProgress","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"closingPeriodPauseTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"currentPeriodFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"currentPeriodRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"delegateVolume","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"delegatedVolume","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"distributeFeesEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"durationPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"extraRewardsActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"feeToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"fixedPeriodReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getAMMVolume","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getAlreadyClaimedRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getBaseReward","outputs":[{"internalType":"uint256","name":"_baseRewards","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getContractFeeFunds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getContractRewardFunds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getLastPeriodOfClaimedRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getRewardFeesAvailable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getRewardsAvailable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getTotalBonus","outputs":[{"internalType":"uint256","name":"returnValue","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"iEscrowThales","outputs":[{"internalType":"contract IEscrowThales","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"initNonReentrant","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_iEscrowThales","type":"address"},{"internalType":"address","name":"_stakingToken","type":"address"},{"internalType":"address","name":"_feeToken","type":"address"},{"internalType":"uint256","name":"_durationPeriod","type":"uint256"},{"internalType":"uint256","name":"_unstakeDurationPeriod","type":"uint256"},{"internalType":"address","name":"_ISNXRewards","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"lastPauseTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastPeriodTimeStamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastUnstakeTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"destAccount","type":"address"}],"name":"mergeAccount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"mergeAccountEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"nominateNewOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"periodExtraReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"periodsOfStaking","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"priceFeed","outputs":[{"internalType":"contract IPriceFeed","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"readOnlyMode","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"sendCCIPMessage","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"sendRoundClosingMessageCrosschain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_thalesAMM","type":"address"},{"internalType":"address","name":"_thalesRangedAMM","type":"address"},{"internalType":"address","name":"_sportsAMM","type":"address"},{"internalType":"address","name":"_priceFeed","type":"address"},{"internalType":"address","name":"_thalesStakingRewardsPool","type":"address"},{"internalType":"address","name":"_addressResolver","type":"address"},{"internalType":"address","name":"_stakingThalesBonusRewardsManager","type":"address"}],"name":"setAddresses","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"_canClaimOnBehalf","type":"bool"}],"name":"setCanClaimOnBehalf","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_escrowThalesContract","type":"address"}],"name":"setEscrow","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_lastPeriodTimestamp","type":"uint256"}],"name":"setLastPeriodTimestamp","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bool","name":"_paused","type":"bool"}],"name":"setPaused","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bool","name":"_claimEnabled","type":"bool"},{"internalType":"bool","name":"_distributeFeesEnabled","type":"bool"},{"internalType":"uint256","name":"_durationPeriod","type":"uint256"},{"internalType":"uint256","name":"_unstakeDurationPeriod","type":"uint256"},{"internalType":"bool","name":"_mergeAccountEnabled","type":"bool"},{"internalType":"bool","name":"_readOnlyMode","type":"bool"},{"internalType":"bool","name":"_sendCCIPMessage","type":"bool"}],"name":"setStakingParameters","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_fixedReward","type":"uint256"},{"internalType":"uint256","name":"_extraReward","type":"uint256"},{"internalType":"bool","name":"_extraRewardsActive","type":"bool"}],"name":"setStakingRewardsParameters","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_ammVault","type":"address"},{"internalType":"bool","name":"value","type":"bool"}],"name":"setSupportedAMMVault","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_sportVault","type":"address"},{"internalType":"bool","name":"value","type":"bool"}],"name":"setSupportedSportVault","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"sportsAMM","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"stakedBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"stakerFeesClaimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"stakerLifetimeRewardsClaimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"stakingThalesBonusRewardsManager","outputs":[{"internalType":"contract IStakingThalesBonusRewardsManager","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"stakingToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"startStakingPeriod","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"startTimeStamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"startUnstake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"supportedAMMVault","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"supportedSportVault","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"thalesAMM","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"thalesRangedAMM","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalEscrowedLastPeriodEnd","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalStakedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalStakedLastPeriodEnd","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"proxyAddress","type":"address"}],"name":"transferOwnershipAtInit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"unstake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"unstakeDurationPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"unstaking","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"unstakingAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_currentPeriodRewards","type":"uint256"},{"internalType":"uint256","name":"_extraRewards","type":"uint256"},{"internalType":"uint256","name":"_revShare","type":"uint256"}],"name":"updateStakingRewards","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"updateVolume","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b50614ce0806100206000396000f3fe608060405234801561001057600080fd5b506004361061048b5760003560e01c806364c8359111610262578063a4bce4ac11610151578063c731a3d1116100ce578063e11cd05511610092578063e11cd05514610b87578063e81a252614610b8f578063eaa8ba7f14610bb5578063ebc7977214610c0d578063f38d00f014610c15578063fd143c0b14610c1d5761048b565b8063c731a3d114610b41578063c992528814610b49578063cb8d751a14610b51578063d66e067714610b77578063df52461a14610b7f5761048b565b8063ba47a5d911610115578063ba47a5d914610aa1578063bd45006214610aa9578063c10c354614610acf578063c3b83f5f14610af5578063c5335ac614610b1b5761048b565b8063a4bce4ac14610a64578063a5b935a414610a6c578063a694fc3a14610a74578063afac7fb114610a91578063b88a802f14610a995761048b565b80638759263f116101df57806393eb2e66116101a357806393eb2e66146109da57806395910db2146109e25780639a09edab146109ea5780639a109bc214610a10578063a00159a814610a365761048b565b80638759263f146109305780638a0ac0ff146109595780638a239de8146109a45780638da5cb5b146109ca57806391b4ded9146109d25761048b565b8063741bef1a11610226578063741bef1a146108ea57806379ba5097146108f25780637a685677146108fa5780637c17f6fc14610920578063847ae197146109285761048b565b806364c835911461083557806366c4c8c71461085b5780636dca3b02146108635780636e3c0d87146108b757806372f702f3146108e25761048b565b806336468b5a1161037e57806353cf4115116102fb578063608daf89116102bf578063608daf89146107ef57806361c01db7146107f757806362139e0e1461081d5780636282719e14610825578063647846a51461082d5761048b565b806353cf4115146107a157806356091ad1146107a9578063567e98f9146107d7578063572e36e6146107df5780635c975abb146107e75761048b565b80634c4e75df116103425780634c4e75df146107355780634ed25b431461075b578063505b149714610763578063507a73281461079157806353a47bb7146107995761048b565b806336468b5a146106d15780633faae534146106f7578063406a7766146106ff57806347dda6ec146107075780634ab179691461072d5761048b565b8063200743541161040c5780632def6620116103d05780632def6620146106615780632f32415814610669578063331e03a81461067157806334dfb2681461069757806335e5d29a146106b45761048b565b80632007435414610607578063203d37181461060f5780632145e92e146106175780632866ed211461061f5780632d2878861461063b5761048b565b80631627540c116104535780631627540c1461054a578063167653911461057057806316c38b3c1461059657806317433c91146105b55780631cb70a95146105e35761048b565b806302c7739b14610490578063080e2b47146104be5780631314f759146104f657806313af40351461051c57806315da506414610542575b600080fd5b6104bc600480360360408110156104a657600080fd5b506001600160a01b038135169060200135610c43565b005b6104e4600480360360208110156104d457600080fd5b50356001600160a01b0316610e73565b60408051918252519081900360200190f35b6104e46004803603602081101561050c57600080fd5b50356001600160a01b0316610e85565b6104bc6004803603602081101561053257600080fd5b50356001600160a01b0316610e98565b6104e4610fad565b6104bc6004803603602081101561056057600080fd5b50356001600160a01b0316610fb3565b6104e46004803603602081101561058657600080fd5b50356001600160a01b031661100f565b6104bc600480360360208110156105ac57600080fd5b5035151561102a565b6104bc600480360360408110156105cb57600080fd5b506001600160a01b03813516906020013515156110a4565b6105eb611110565b604080516001600160a01b039092168252519081900360200190f35b6104e4611124565b6105eb61112a565b6104bc611139565b61062761114b565b604080519115158252519081900360200190f35b6104e46004803603602081101561065157600080fd5b50356001600160a01b0316611154565b6104bc611166565b6105eb6112e6565b6104e46004803603602081101561068757600080fd5b50356001600160a01b03166112fa565b6104bc600480360360208110156106ad57600080fd5b503561130c565b6104bc600480360360208110156106ca57600080fd5b503561169a565b6104e4600480360360208110156106e757600080fd5b50356001600160a01b0316611726565b6104e4611871565b6104e46118fb565b6106276004803603602081101561071d57600080fd5b50356001600160a01b0316611901565b6104bc611916565b6104e46004803603602081101561074b57600080fd5b50356001600160a01b0316611a96565b6104e4611ab1565b6104bc6004803603604081101561077957600080fd5b506001600160a01b0381351690602001351515611ab7565b6104bc611bd2565b6105eb61202f565b61062761203e565b6104bc600480360360408110156107bf57600080fd5b506001600160a01b0381351690602001351515612047565b6104e46120b3565b6105eb6120b9565b6106276120c8565b6104e46120d1565b6104bc6004803603602081101561080d57600080fd5b50356001600160a01b03166120d7565b6104e461224a565b6104bc612250565b6105eb612302565b6104e46004803603602081101561084b57600080fd5b50356001600160a01b0316612311565b6105eb612323565b6104bc600480360360e081101561087957600080fd5b506001600160a01b03813581169160208101358216916040820135811691606081013582169160808201359160a08101359160c09091013516612332565b6104bc600480360360608110156108cd57600080fd5b508035906020810135906040013515156124ee565b6105eb612557565b6105eb612566565b6104bc612575565b6104e46004803603602081101561091057600080fd5b50356001600160a01b0316612631565b6104e461263c565b610627612642565b6104bc6004803603606081101561094657600080fd5b508035906020810135906040013561264b565b6104bc600480360360e081101561096f57600080fd5b5080351515906020810135151590604081013590606081013590608081013515159060a081013515159060c001351515612c3f565b6104e4600480360360208110156109ba57600080fd5b50356001600160a01b0316612d0f565b6105eb612d2a565b6104e4612d39565b6104e4612d3f565b6104e4612d45565b6104e460048036036020811015610a0057600080fd5b50356001600160a01b0316612d4b565b6104e460048036036020811015610a2657600080fd5b50356001600160a01b0316612d51565b61062760048036036040811015610a4c57600080fd5b506001600160a01b0381358116916020013516612e97565b610627612eb7565b610627612ec0565b6104bc60048036036020811015610a8a57600080fd5b5035612ed0565b610627612fa7565b6104bc612fd3565b6104e461306d565b6105eb60048036036020811015610abf57600080fd5b50356001600160a01b0316613073565b6104bc60048036036020811015610ae557600080fd5b50356001600160a01b031661308e565b6104bc60048036036020811015610b0b57600080fd5b50356001600160a01b0316613217565b6104bc60048036036020811015610b3157600080fd5b50356001600160a01b0316613336565b6106276136ec565b6105eb6136f5565b61062760048036036020811015610b6757600080fd5b50356001600160a01b0316613704565b6104e4613719565b610627613764565b6104e4613774565b6104bc60048036036020811015610ba557600080fd5b50356001600160a01b031661377a565b6104bc600480360360e0811015610bcb57600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135821691608082013581169160a081013582169160c0909101351661381f565b6104bc613914565b6104e4613977565b61062760048036036020811015610c3357600080fd5b50356001600160a01b031661397d565b6001600160a01b03821615801590610c5b5750600081115b610c9d576040805162461bcd60e51b815260206004820152600e60248201526d496e76616c696420706172616d7360901b604482015290519081900360640190fd5b6001600160a01b038281166000908152607260205260409020541615610cdc576001600160a01b03918216600090815260726020526040902054909116905b6058546001600160a01b0316331480610cff57506066546001600160a01b031633145b80610d1457506067546001600160a01b031633145b80610d2e57503360009081526073602052604090205460ff165b80610d4857503360009081526074602052604090205460ff165b610d8b576040805162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015290519081900360640190fd5b610d9481613992565b6077549091506001600160a01b031615610e2757607754603e54604080516352a31c0760e01b81526001600160a01b038681166004830152336024830152604482018690526064820193909352905191909216916352a31c0791608480830192600092919082900301818387803b158015610e0e57600080fd5b505af1158015610e22573d6000803e3d6000fd5b505050505b604080516001600160a01b038416815260208101839052338183015290517fb43a20c9abfed93eb48264a3acf807336352ba8cb6ee42c1754b1b1b280a20b99181900360600190a15050565b604c6020526000908152604090205481565b6000610e9082613a1b565b90505b919050565b6001600160a01b038116610ef3576040805162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015290519081900360640190fd5b603454600160a01b900460ff1615610f3c5760405162461bcd60e51b81526004018080602001828103825260298152602001806149f56029913960400191505060405180910390fd5b6034805460ff60a01b1916600160a01b179055603380546001600160a01b0383166001600160a01b031990911681179091556040805160008152602081019290925280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a150565b60465481565b610fbb613b06565b603480546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229181900360200190a150565b6001600160a01b031660009081526056602052604090205490565b611032613b06565b60385460ff1615158115151415611048576110a1565b6038805460ff1916821515179081905560ff161561106557426037555b6038546040805160ff90921615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec59181900360200190a15b50565b6110ac613b06565b6001600160a01b038216600081815260736020908152604091829020805460ff191685151590811790915582519384529083015280517fd2a8401466e7483577592b4b5160af1ba59060100f12387853477637096cfb919281900390910190a15050565b605b5461010090046001600160a01b031681565b603f5481565b6066546001600160a01b031681565b611141613b06565b611149613b4f565b565b604a5460ff1681565b60556020526000908152604090205481565b60385460ff16156111a85760405162461bcd60e51b815260040180806020018281038252603c815260200180614bc6603c913960400191505060405180910390fd5b3360009081526054602052604090205460ff166111f65760405162461bcd60e51b815260040180806020018281038252602a815260200180614a47602a913960400191505060405180910390fd5b60415461120a90429063ffffffff613e2c16565b33600090815260536020526040902054106112565760405162461bcd60e51b8152600401808060200182810382526029815260200180614a1e6029913960400191505060405180910390fd5b336000818152605460209081526040808320805460ff1916905560559091529020546039549091611297916001600160a01b0316908363ffffffff613e8e16565b336000818152605560209081526040808320929092558151928352820183905280517f0f5bb82176feb1b5e747e28471aa92156a04d9f3ab9f45f28e2d704232b93f759281900390910190a150565b60385461010090046001600160a01b031681565b60536020526000908152604090205481565b60385460ff161561134e5760405162461bcd60e51b815260040180806020018281038252603c815260200180614bc6603c913960400191505060405180910390fd5b60008111611396576040805162461bcd60e51b815260206004820152601060248201526f043616e6e6f7420756e7374616b6520360841b604482015290519081900360640190fd5b336000908152605660205260409020548111156113e45760405162461bcd60e51b8152600401808060200182810382526024815260200180614c026024913960400191505060405180910390fd5b3360009081526054602052604090205460ff16156114335760405162461bcd60e51b815260040180806020018281038252602e815260200180614b5a602e913960400191505060405180910390fd5b600061143e33613ee5565b111561144d5761144d33613f34565b33600090815260536020908152604080832042905560549091529020805460ff19166001179055604d54611487908263ffffffff613e2c16565b604d5533600090815260556020908152604080832084905560569091529020546114b7908263ffffffff613e2c16565b33600090815260566020526040902081905561162957603854604080516334c78ae560e11b8152336004820152905160009261010090046001600160a01b03169163698f15ca916024808301926020929190829003018186803b15801561151d57600080fd5b505afa158015611531573d6000803e3d6000fd5b505050506040513d602081101561154757600080fd5b5051111561162957603854604080516334c78ae560e11b815233600482015290516101009092046001600160a01b031691635817d04291839163698f15ca91602480820192602092909190829003018186803b1580156115a657600080fd5b505afa1580156115ba573d6000803e3d6000fd5b505050506040513d60208110156115d057600080fd5b5051604080516001600160e01b031960e085901b168152600481019290925251602480830192600092919082900301818387803b15801561161057600080fd5b505af1158015611624573d6000803e3d6000fd5b505050505b604154336000818152605360205260409020547f30797de805f090008d8b19fa0c6f92d0f164789f64d6f7a1b097fbf0b1abac6b9261166e919063ffffffff6142b016565b604080516001600160a01b0390931683526020830191909152818101849052519081900360600190a150565b6116a2613b06565b614650603f540381116116eb576040805162461bcd60e51b815260206004820152600c60248201526b546f6f20666172206261636b60a01b604482015290519081900360640190fd5b603f8190556040805182815290517fd1956985dae3dbe5da7d4db0d0abc90d01284cf79627ffef5538d2cd006901049181900360200190a150565b6077546000906001600160a01b0316158015906117b95750607760009054906101000a90046001600160a01b03166001600160a01b0316635bd90b486040518163ffffffff1660e01b815260040160206040518083038186803b15801561178c57600080fd5b505afa1580156117a0573d6000803e3d6000fd5b505050506040513d60208110156117b657600080fd5b50515b15610e9357607754603e5460408051638d61c38b60e01b81526001600160a01b03868116600483015260001990930160248201529051610e9093670de0b6b3a76400009361186593911691638d61c38b91604480820192602092909190829003018186803b15801561182a57600080fd5b505afa15801561183e573d6000803e3d6000fd5b505050506040513d602081101561185457600080fd5b50516047549063ffffffff61430a16565b9063ffffffff61436316565b603954605b54604080516370a0823160e01b81526101009092046001600160a01b039081166004840152905160009391909116916370a08231916024808301926020929190829003018186803b1580156118ca57600080fd5b505afa1580156118de573d6000803e3d6000fd5b505050506040513d60208110156118f457600080fd5b5051905090565b60795481565b60736020526000908152604090205460ff1681565b60385460ff16156119585760405162461bcd60e51b815260040180806020018281038252603c815260200180614bc6603c913960400191505060405180910390fd5b3360009081526054602052604090205460ff166119bc576040805162461bcd60e51b815260206004820152601860248201527f4163636f756e74206973206e6f7420756e7374616b696e670000000000000000604482015290519081900360640190fd5b6119c5336143cd565b60006119d033613ee5565b11156119df576119df33613f34565b336000908152605460209081526040808320805460ff191690556055909152902054604d54611a139163ffffffff6142b016565b604d5533600090815260556020908152604080832054605690925290912054611a419163ffffffff6142b016565b336000818152605660209081526040808320949094556055815283822091909155825191825291517f725ee3b9a70aadcb1e002c94935880d7f515620783a5144c90e39201dc6f92da929181900390910190a1565b6001600160a01b031660009081526057602052604090205490565b60475481565b60385460ff1615611af95760405162461bcd60e51b815260040180806020018281038252603c815260200180614bc6603c913960400191505060405180910390fd5b6001600160a01b03821615801590611b1a57506001600160a01b0382163314155b611b5d576040805162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015290519081900360640190fd5b3360008181526070602090815260408083206001600160a01b03871680855290835292819020805486151560ff19909116811790915581519485529184019290925282820152517fc939ba7d9b3e1a4e6505db209888366a551f46a85918944eb89becb92289935b9181900360600190a15050565b603580546001019081905560385460ff1615611c1f5760405162461bcd60e51b815260040180806020018281038252603c815260200180614bc6603c913960400191505060405180910390fd5b600060425411611c76576040805162461bcd60e51b815260206004820152601e60248201527f5374616b696e6720706572696f6420686173206e6f7420737461727465640000604482015290519081900360640190fd5b604054603f54611c8b9163ffffffff6142b016565b421015611cc95760405162461bcd60e51b8152600401808060200182810382526039815260200180614aef6039913960400191505060405180910390fd5b607854600160a81b900460ff1615611d1c576040805162461bcd60e51b8152602060048201526011602482015270436c6f73696e67496e50726f677265737360781b604482015290519081900360640190fd5b603860019054906101000a90046001600160a01b03166001600160a01b031663acfabbe46040518163ffffffff1660e01b8152600401602060405180830381600087803b158015611d6c57600080fd5b505af1158015611d80573d6000803e3d6000fd5b505050506040513d6020811015611d9657600080fd5b505042603f5560385460408051635d13850560e01b815290516101009092046001600160a01b031691635d13850591600480820192602092909190829003018186803b158015611de557600080fd5b505afa158015611df9573d6000803e3d6000fd5b505050506040513d6020811015611e0f57600080fd5b5051603e55603854604080516347d3681760e11b81529051611f0c9261010090046001600160a01b031691638fa6d02e916004808301926020929190829003018186803b158015611e5f57600080fd5b505afa158015611e73573d6000803e3d6000fd5b505050506040513d6020811015611e8957600080fd5b50516038546040805163b9d1c70b60e01b815290516101009092046001600160a01b03169163b9d1c70b91600480820192602092909190829003018186803b158015611ed457600080fd5b505afa158015611ee8573d6000803e3d6000fd5b505050506040513d6020811015611efe57600080fd5b50519063ffffffff613e2c16565b606355604654604355603a54604080516370a0823160e01b815230600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015611f6057600080fd5b505afa158015611f74573d6000803e3d6000fd5b505050506040513d6020811015611f8a57600080fd5b5051604455604d54606255607a5460ff1615611fa857611fa8613b4f565b7f80827f48a8070d07af7887688320aadf44499e3a2751fc41cc965870cf0627d7603e54603f54604051808381526020018281526020019250505060405180910390a160355481146110a1576040805162461bcd60e51b815260206004820152601f60248201526000805160206149a0833981519152604482015290519081900360640190fd5b6034546001600160a01b031681565b60455460ff1681565b61204f613b06565b6001600160a01b038216600081815260746020908152604091829020805460ff191685151590811790915582519384529083015280517fcf84063977a2a7766d440ee9919a260c5e0add05c19db1f47b31250b89c73e399281900390910190a15050565b604d5490565b6058546001600160a01b031681565b60385460ff1681565b60625481565b603580546001019081905560385460ff16156121245760405162461bcd60e51b815260040180806020018281038252603c815260200180614bc6603c913960400191505060405180910390fd5b6001600160a01b0382161580159061214557506001600160a01b0382163314155b612188576040805162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015290519081900360640190fd5b6001600160a01b038216600090815260706020908152604080832033845290915290205460ff166121f9576040805162461bcd60e51b815260206004820152601660248201527521b0b73737ba1031b630b4b69037b7103132b430b63360511b604482015290519081900360640190fd5b61220282613f34565b6035548114612246576040805162461bcd60e51b815260206004820152601f60248201526000805160206149a0833981519152604482015290519081900360640190fd5b5050565b60405481565b612258613b06565b604254156122ad576040805162461bcd60e51b815260206004820152601b60248201527f5374616b696e672068617320616c726561647920737461727465640000000000604482015290519081900360640190fd5b4260428190556000603e819055603f9190915560518190556052819055604d819055604e819055604f8190556040517f7c01398e484f9a82feaa276906d5d1f84867a0ff5a5bd9a485d4357f58d401839190a1565b603a546001600160a01b031681565b604b6020526000908152604090205481565b6077546001600160a01b031681565b600054610100900460ff168061234b575061234b614551565b80612359575060005460ff16155b6123945760405162461bcd60e51b815260040180806020018281038252602e815260200180614ac1602e913960400191505060405180910390fd5b600054610100900460ff161580156123bf576000805460ff1961ff0019909116610100171660011790555b6123c888610e98565b6123d0613914565b60388054610100600160a81b0319166101006001600160a01b038a811691820292909217909255603980546001600160a01b03199081168a84161791829055603a80549091168984161790556040805163095ea7b360e01b8152600481019490945260001960248501525191169163095ea7b39160448083019260209291908290030181600087803b15801561246557600080fd5b505af1158015612479573d6000803e3d6000fd5b505050506040513d602081101561248f57600080fd5b505060408490556041839055690ed2b525841adfc00000604655690472698b413b43200000604755603b80546001600160a01b0319166001600160a01b03841617905580156124e4576000805461ff00191690555b5050505050505050565b6124f6613b06565b60468390556047829055605b805482151560ff199091168117909155604080518581526020810185905280820192909252517ff2192442b5560227e5c603bd8ec631a14b2fe42f35cf4e8e2083502de9571bb49181900360600190a1505050565b6039546001600160a01b031681565b603d546001600160a01b031681565b6034546001600160a01b031633146125be5760405162461bcd60e51b81526004018080602001828103825260358152602001806149c06035913960400191505060405180910390fd5b603354603454604080516001600160a01b03938416815292909116602083015280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a160348054603380546001600160a01b03199081166001600160a01b03841617909155169055565b6000610e9082613ee5565b603e5481565b607a5460ff1681565b6035805460010190819055607854600160a01b900460ff16612bac576065546040805163bf40fac160e01b8152602060048201819052601360248301527221b937b9b9a1b430b4b721b7b63632b1ba37b960691b604483015291516001600160a01b039093169263bf40fac192606480840193919291829003018186803b1580156126d557600080fd5b505afa1580156126e9573d6000803e3d6000fd5b505050506040513d60208110156126ff57600080fd5b50516001600160a01b031633148061272157506033546001600160a01b031633145b61275c576040805162461bcd60e51b81526020600482015260076024820152660496e76434349560cc1b604482015290519081900360640190fd5b607854600160a81b900460ff166127ad576040805162461bcd60e51b815260206004820152601060248201526f139bdd125b90db1bdcd954195c9a5bd960821b604482015290519081900360640190fd5b60465484111580156127c157506046548311155b80156127d257506046546005028211155b61280d5760405162461bcd60e51b8152600401808060200182810382526021815260200180614c8b6021913960400191505060405180910390fd5b6065546040805163045f670760e21b8152602060048201819052600d60248301526c29b0b332a137bc213ab33332b960991b604483015291516000936001600160a01b03169263117d9c1c9260648082019391829003018186803b15801561287457600080fd5b505afa158015612888573d6000803e3d6000fd5b505050506040513d602081101561289e57600080fd5b5051603a54604080516370a0823160e01b8152306004820152905192935060009283926001600160a01b0316916370a08231916024808301926020929190829003018186803b1580156128f057600080fd5b505afa158015612904573d6000803e3d6000fd5b505050506040513d602081101561291a57600080fd5b5051905061292785614557565b6044558215612b69576065546040805163bf40fac160e01b8152602060048201819052600d60248301526c29b0b332a137bc213ab33332b960991b604483015291516000936001600160a01b03169263bf40fac19260648082019391829003018186803b15801561299757600080fd5b505afa1580156129ab573d6000803e3d6000fd5b505050506040513d60208110156129c157600080fd5b5051604454909150821015612ac857604454603a54604080516370a0823160e01b81526001600160a01b0385811660048301529151938690039391909216916370a08231916024808301926020929190829003018186803b158015612a2557600080fd5b505afa158015612a39573d6000803e3d6000fd5b505050506040513d6020811015612a4f57600080fd5b50511015612a605760019250612ac3565b806001600160a01b0316639ffcb31683604454036040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015612aaa57600080fd5b505af1158015612abe573d6000803e3d6000fd5b505050505b612b67565b6000604454118015612adb575081604454105b15612b6757603a54604480546040805163a9059cbb60e01b81526001600160a01b03868116600483015292870360248201529051919093169263a9059cbb92818101926020929091908290030181600087803b158015612b3a57600080fd5b505af1158015612b4e573d6000803e3d6000fd5b505050506040513d6020811015612b6457600080fd5b50505b505b604387905560478690556078805460ff60a81b191690556037546079541415612ba857821580612b965750815b6038805460ff19169115159190911790555b5050505b7fb4873f5e95851bc84e2c197ca35129e61b53e3525c5d563b4dfd9307833f4dcc8484612bd885614557565b60408051938452602084019290925282820152519081900360600190a16035548114612c39576040805162461bcd60e51b815260206004820152601f60248201526000805160206149a0833981519152604482015290519081900360640190fd5b50505050565b612c47613b06565b604a805488151560ff1991821681179092556045805489151590831681179091556040888155604188905560718054881515908516811790915560788054881515600160a01b810260ff60a01b1990921691909117909155607a8054881515961686179055825195865260208601939093528482018a905260608501899052608085015260a084019190915260c0830191909152517fd0b7c05d30d50a3a23a9835892652aebc30da318b53c90521825ea7698e590a09181900360e00190a150505050505050565b6001600160a01b03166000908152604b602052604090205490565b6033546001600160a01b031681565b60375481565b60415481565b60635481565b50600090565b603e546001600160a01b03821660009081526061602052604081205490911480612d9157506001600160a01b038216600090815260566020526040902054155b80612db55750603e546001600160a01b038316600090815260576020526040902054145b80612dc05750606254155b610e9357610e90612dde6063546062546142b090919063ffffffff16565b604354603854604080516317640e0760e01b81526001600160a01b03888116600483015291516118659493612e8b9361010090910416916317640e07916024808301926020929190829003018186803b158015612e3a57600080fd5b505afa158015612e4e573d6000803e3d6000fd5b505050506040513d6020811015612e6457600080fd5b50516001600160a01b0388166000908152605660205260409020549063ffffffff6142b016565b9063ffffffff61430a16565b607060209081526000928352604080842090915290825290205460ff1681565b605b5460ff1681565b607854600160a01b900460ff1681565b603580546001019081905560385460ff1615612f1d5760405162461bcd60e51b815260040180806020018281038252603c815260200180614bc6603c913960400191505060405180910390fd5b612f288233336145e1565b604080513381526020810184905281517f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d929181900390910190a16035548114612246576040805162461bcd60e51b815260206004820152601f60248201526000805160206149a0833981519152604482015290519081900360640190fd5b600080604254118015612fce5750604054603f54612fca9163ffffffff6142b016565b4210155b905090565b603580546001019081905560385460ff16156130205760405162461bcd60e51b815260040180806020018281038252603c815260200180614bc6603c913960400191505060405180910390fd5b61302933613f34565b60355481146110a1576040805162461bcd60e51b815260206004820152601f60248201526000805160206149a0833981519152604482015290519081900360640190fd5b60445481565b6072602052600090815260409020546001600160a01b031681565b613096613b06565b60385461010090046001600160a01b031615613139576039546038546040805163095ea7b360e01b81526101009092046001600160a01b039081166004840152600060248401819052915193169263095ea7b3926044808201936020939283900390910190829087803b15801561310c57600080fd5b505af1158015613120573d6000803e3d6000fd5b505050506040513d602081101561313657600080fd5b50505b60388054610100600160a81b0319166101006001600160a01b03848116918202929092179092556039546040805163095ea7b360e01b8152600481019490945260001960248501525191169163095ea7b39160448083019260209291908290030181600087803b1580156131ac57600080fd5b505af11580156131c0573d6000803e3d6000fd5b505050506040513d60208110156131d657600080fd5b5050604080516001600160a01b038316815290517feb1a4b1e230d212e1644ea31e3890084e2fa17ddee990e46a46e198e1728c4a09181900360200190a150565b61321f613b06565b6001600160a01b03811661326c576040805162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015290519081900360640190fd5b603454600160a81b900460ff16156132c1576040805162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481d1c985b9cd9995c9c9959606a1b604482015290519081900360640190fd5b603380546001600160a01b038084166001600160a01b03199092168217928390556034805460ff60a81b1916600160a81b17905560408051939091168352602083019190915280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a150565b60385460ff16156133785760405162461bcd60e51b815260040180806020018281038252603c815260200180614bc6603c913960400191505060405180910390fd5b60715460ff166133cf576040805162461bcd60e51b815260206004820152601960248201527f4d65726765206163636f756e742069732064697361626c656400000000000000604482015290519081900360640190fd5b6001600160a01b038116158015906133f057506001600160a01b0381163314155b613433576040805162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015290519081900360640190fd5b61343c33613ee5565b15801561344f575061344d81613ee5565b155b61348a5760405162461bcd60e51b815260040180806020018281038252603b815260200180614c26603b913960400191505060405180910390fd5b3360009081526054602052604090205460ff161580156134c357506001600160a01b03811660009081526054602052604090205460ff16155b6134fe5760405162461bcd60e51b815260040180806020018281038252603e815260200180614b88603e913960400191505060405180910390fd5b60385460408051630282a2ed60e21b81523360048201526001600160a01b038481166024830152915161010090930490911691630a0a8bb49160448082019260009290919082900301818387803b15801561355857600080fd5b505af115801561356c573d6000803e3d6000fd5b505033600090815260566020526040808220546001600160a01b03861683529120546135a09350915063ffffffff6142b016565b6001600160a01b038216600081815260566020908152604080832094909455338252604b90528281205491815291909120546135e19163ffffffff6142b016565b6001600160a01b0382166000818152604b6020908152604080832094909455338252604c90528281205491815291909120546136229163ffffffff6142b016565b6001600160a01b0382166000818152604c6020818152604080842095909555603e546057808352868520829055606180845287862092909255338086526053845287862086905560548452878620805460ff191690556055845287862086905560568452878620869055604b8452878620869055938352868520859055825285842084905581528483209290925583519081529081019190915281517fa0fc26d627101bedf9c6cedb33e9eeac3fa2a7d508f89b597134bcee1a12d32c929181900390910190a150565b60715460ff1681565b6067546001600160a01b031681565b60546020526000908152604090205460ff1681565b603a54604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b1580156118ca57600080fd5b607854600160a81b900460ff1681565b60435481565b60385460ff16156137bc5760405162461bcd60e51b815260040180806020018281038252603c815260200180614bc6603c913960400191505060405180910390fd5b3360009081526072602090815260409182902080546001600160a01b0319166001600160a01b038516908117909155825190815291517f0c417702befaa0d74611c15e4278a897f344514ffbfbd4ea9a6e9168be46b8da9281900390910190a150565b613827613b06565b605880546001600160a01b03808a166001600160a01b03199283168117909355606680548a83169084168117909155606780548a84169085168117909155603d80548a85169086168117909155605b80548a86166101008102610100600160a81b031990921691909117909155606580548a8716908816811790915560778054968a16969097168617909655604080519788526020880194909452868401929092526060860152608085015260a084019290925260c0830152517fbe8209a2817cacf2137f586f29208a496d2d159efa011f3937e8172892826a9a9181900360e00190a150505050505050565b60365460ff1615613962576040805162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b604482015290519081900360640190fd5b6036805460ff19166001908117909155603555565b60425481565b60746020526000908152604090205460ff1681565b603a546040805163313ce56760e01b815290516000926001600160a01b03169163313ce567916004808301926020929190829003018186803b1580156139d757600080fd5b505afa1580156139eb573d6000803e3d6000fd5b505050506040513d6020811015613a0157600080fd5b5051600614613a105781610e90565b5064e8d4a510000290565b600080613a2783612d51565b905080613a38576000915050610e93565b613aff613a526063546062546142b090919063ffffffff16565b604454603854604080516317640e0760e01b81526001600160a01b03898116600483015291516118659493612e8b9361010090910416916317640e07916024808301926020929190829003018186803b158015613aae57600080fd5b505afa158015613ac2573d6000803e3d6000fd5b505050506040513d6020811015613ad857600080fd5b50516001600160a01b0389166000908152605660205260409020549063ffffffff6142b016565b9392505050565b6033546001600160a01b031633146111495760405162461bcd60e51b815260040180806020018281038252602f815260200180614a71602f913960400191505060405180910390fd5b6065546040805163045f670760e21b8152602060048201819052601360248301527221b937b9b9a1b430b4b721b7b63632b1ba37b960691b604483015291516001600160a01b039093169263117d9c1c92606480840193919291829003018186803b158015613bbd57600080fd5b505afa158015613bd1573d6000803e3d6000fd5b505050506040513d6020811015613be757600080fd5b50511561114957607854600160a01b900460ff16613c29576038805460ff191660011790556078805460ff60a81b1916600160a81b1790554260378190556079555b6065546040805163bf40fac160e01b8152602060048201819052601360248301527221b937b9b9a1b430b4b721b7b63632b1ba37b960691b604483015291516001600160a01b039093169263bf40fac192606480840193919291829003018186803b158015613c9757600080fd5b505afa158015613cab573d6000803e3d6000fd5b505050506040513d6020811015613cc157600080fd5b5051606254606354607754603e546040805163df022bf560e01b81526000199092016004830152516001600160a01b03958616956334bd229c959493169163df022bf5916024808301926020929190829003018186803b158015613d2457600080fd5b505afa158015613d38573d6000803e3d6000fd5b505050506040513d6020811015613d4e57600080fd5b5051603a54604080516370a0823160e01b81523060048201529051613dcd926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015613d9c57600080fd5b505afa158015613db0573d6000803e3d6000fd5b505050506040513d6020811015613dc657600080fd5b5051613992565b6040518563ffffffff1660e01b815260040180858152602001848152602001838152602001828152602001945050505050600060405180830381600087803b158015613e1857600080fd5b505af1158015612c39573d6000803e3d6000fd5b600082821115613e83576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052613ee0908490614787565b505050565b600080613ef183612d51565b905080613f02576000915050610e93565b605b5460ff16613f13579050610e93565b613f2c613f1f84611726565b829063ffffffff6142b016565b915050610e93565b60385460ff1615613f765760405162461bcd60e51b815260040180806020018281038252603c815260200180614bc6603c913960400191505060405180910390fd5b604a5460ff16613fcd576040805162461bcd60e51b815260206004820152601860248201527f436c61696d696e67206973206e6f7420656e61626c65642e0000000000000000604482015290519081900360640190fd5b600060425411614024576040805162461bcd60e51b815260206004820152601e60248201527f5374616b696e6720706572696f6420686173206e6f7420737461727465640000604482015290519081900360640190fd5b603e546001600160a01b03821660009081526057602052604090205410614084576040805162461bcd60e51b815260206004820152600f60248201526e105b1c9958591e4818db185a5b5959608a1b604482015290519081900360640190fd5b60455460ff161561415e57600061409a82613a1b565b9050801561415c57603a546140bf906001600160a01b0316838363ffffffff613e8e16565b6001600160a01b0382166000908152604c60205260409020546140e8908263ffffffff6142b016565b6001600160a01b0383166000908152604c6020526040902055605254614114908263ffffffff6142b016565b605255604080516001600160a01b03841681526020810183905281517f5b16e1043a283423361eb77682c99aff55948b34296846800a1a7dc9547a89fc929181900390910190a15b505b600061416982613ee5565b9050801561429057605b546040805163b01ca88f60e01b81526001600160a01b0385811660048301526024820185905291516101009093049091169163b01ca88f9160448082019260009290919082900301818387803b1580156141cc57600080fd5b505af11580156141e0573d6000803e3d6000fd5b5050506001600160a01b0383166000908152604b602052604090205461420d91508263ffffffff6142b016565b6001600160a01b0383166000908152604b6020526040902055605154614239908263ffffffff6142b016565b6051557fdacbdde355ba930696a362ea6738feb9f8bd52dfb3d81947558fd3217e23e325828261426882612d51565b604080516001600160a01b039094168452602084019290925282820152519081900360600190a15b50603e546001600160a01b03909116600090815260576020526040902055565b600082820183811015613aff576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008261431957506000613e88565b8282028284828161432657fe5b0414613aff5760405162461bcd60e51b8152600401808060200182810382526021815260200180614aa06021913960400191505060405180910390fd5b60008082116143b9576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b60008284816143c457fe5b04949350505050565b6001600160a01b0381166000908152605660205260409020546110a157603854604080516334c78ae560e11b81526001600160a01b038481166004830152915160009361010090049092169163698f15ca91602480820192602092909190829003018186803b15801561443f57600080fd5b505afa158015614453573d6000803e3d6000fd5b505050506040513d602081101561446957600080fd5b505111156110a157603854604080516334c78ae560e11b81526001600160a01b03848116600483015291516101009093049091169163ad6d15de91839163698f15ca91602480820192602092909190829003018186803b1580156144cc57600080fd5b505afa1580156144e0573d6000803e3d6000fd5b505050506040513d60208110156144f657600080fd5b5051604080516001600160e01b031960e085901b168152600481019290925251602480830192600092919082900301818387803b15801561453657600080fd5b505af115801561454a573d6000803e3d6000fd5b5050505050565b303b1590565b603a546040805163313ce56760e01b815290516000926001600160a01b03169163313ce567916004808301926020929190829003018186803b15801561459c57600080fd5b505afa1580156145b0573d6000803e3d6000fd5b505050506040513d60208110156145c657600080fd5b50516006146145d55781610e90565b5064e8d4a51000900490565b600060425411614638576040805162461bcd60e51b815260206004820152601e60248201527f5374616b696e6720706572696f6420686173206e6f7420737461727465640000604482015290519081900360640190fd5b6000831161467e576040805162461bcd60e51b815260206004820152600e60248201526d043616e6e6f74207374616b6520360941b604482015290519081900360640190fd5b6001600160a01b03821660009081526054602052604090205460ff16156146d65760405162461bcd60e51b8152600401808060200182810382526032815260200180614b286032913960400191505060405180910390fd5b60006146e183613ee5565b11156146f0576146f082613f34565b603e546001600160a01b038316600090815260616020526040902055614715826143cd565b604d54614728908463ffffffff6142b016565b604d556001600160a01b038216600090815260566020526040902054614754908463ffffffff6142b016565b6001600160a01b03808416600090815260566020526040902091909155603954613ee0911682308663ffffffff61493f16565b614799826001600160a01b0316614999565b6147ea576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106148285780518252601f199092019160209182019101614809565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811461488a576040519150601f19603f3d011682016040523d82523d6000602084013e61488f565b606091505b5091509150816148e6576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115612c395780806020019051602081101561490257600080fd5b5051612c395760405162461bcd60e51b815260040180806020018281038252602a815260200180614c61602a913960400191505060405180910390fd5b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052612c39908590614787565b3b15159056fe5265656e7472616e637947756172643a207265656e7472616e742063616c6c00596f75206d757374206265206e6f6d696e61746564206265666f726520796f752063616e20616363657074206f776e657273686970416c726561647920696e697469616c697a65642c20757365206e6f6d696e6174654e65774f776e657243616e6e6f7420756e7374616b65207965742c20636f6f6c646f776e206e6f7420657870697265642e4163636f756e7420686173206e6f742074726967676572656420756e7374616b6520636f6f6c646f776e4f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564412066756c6c20706572696f6420686173206e6f74207061737365642073696e636520746865206c61737420636c6f73656420706572696f64546865207374616b6572206973207061757365642066726f6d207374616b696e672064756520746f20756e7374616b696e674163636f756e742068617320616c72656164792074726967676572656420756e7374616b6520636f6f6c646f776e43616e6e6f74206d657267652c2063616e63656c20756e7374616b696e67206f6e20626f7468206163636f756e7473206265666f7265206d657267696e675468697320616374696f6e2063616e6e6f7420626520706572666f726d6564207768696c652074686520636f6e7472616374206973207061757365644163636f756e7420646f65736e7420686176652074686174206d756368207374616b656443616e6e6f74206d657267652c20636c61696d2072657761726473206f6e20626f7468206163636f756e7473206265666f7265206d657267696e675361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656452656a65637465642064756520746f20737573706963696f75732076616c756573a265627a7a723158209d97c81f95d047d4331c4ff98b17ffc12e4f8c946918ed45e316c5ce3570a39e64736f6c63430005100032

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061048b5760003560e01c806364c8359111610262578063a4bce4ac11610151578063c731a3d1116100ce578063e11cd05511610092578063e11cd05514610b87578063e81a252614610b8f578063eaa8ba7f14610bb5578063ebc7977214610c0d578063f38d00f014610c15578063fd143c0b14610c1d5761048b565b8063c731a3d114610b41578063c992528814610b49578063cb8d751a14610b51578063d66e067714610b77578063df52461a14610b7f5761048b565b8063ba47a5d911610115578063ba47a5d914610aa1578063bd45006214610aa9578063c10c354614610acf578063c3b83f5f14610af5578063c5335ac614610b1b5761048b565b8063a4bce4ac14610a64578063a5b935a414610a6c578063a694fc3a14610a74578063afac7fb114610a91578063b88a802f14610a995761048b565b80638759263f116101df57806393eb2e66116101a357806393eb2e66146109da57806395910db2146109e25780639a09edab146109ea5780639a109bc214610a10578063a00159a814610a365761048b565b80638759263f146109305780638a0ac0ff146109595780638a239de8146109a45780638da5cb5b146109ca57806391b4ded9146109d25761048b565b8063741bef1a11610226578063741bef1a146108ea57806379ba5097146108f25780637a685677146108fa5780637c17f6fc14610920578063847ae197146109285761048b565b806364c835911461083557806366c4c8c71461085b5780636dca3b02146108635780636e3c0d87146108b757806372f702f3146108e25761048b565b806336468b5a1161037e57806353cf4115116102fb578063608daf89116102bf578063608daf89146107ef57806361c01db7146107f757806362139e0e1461081d5780636282719e14610825578063647846a51461082d5761048b565b806353cf4115146107a157806356091ad1146107a9578063567e98f9146107d7578063572e36e6146107df5780635c975abb146107e75761048b565b80634c4e75df116103425780634c4e75df146107355780634ed25b431461075b578063505b149714610763578063507a73281461079157806353a47bb7146107995761048b565b806336468b5a146106d15780633faae534146106f7578063406a7766146106ff57806347dda6ec146107075780634ab179691461072d5761048b565b8063200743541161040c5780632def6620116103d05780632def6620146106615780632f32415814610669578063331e03a81461067157806334dfb2681461069757806335e5d29a146106b45761048b565b80632007435414610607578063203d37181461060f5780632145e92e146106175780632866ed211461061f5780632d2878861461063b5761048b565b80631627540c116104535780631627540c1461054a578063167653911461057057806316c38b3c1461059657806317433c91146105b55780631cb70a95146105e35761048b565b806302c7739b14610490578063080e2b47146104be5780631314f759146104f657806313af40351461051c57806315da506414610542575b600080fd5b6104bc600480360360408110156104a657600080fd5b506001600160a01b038135169060200135610c43565b005b6104e4600480360360208110156104d457600080fd5b50356001600160a01b0316610e73565b60408051918252519081900360200190f35b6104e46004803603602081101561050c57600080fd5b50356001600160a01b0316610e85565b6104bc6004803603602081101561053257600080fd5b50356001600160a01b0316610e98565b6104e4610fad565b6104bc6004803603602081101561056057600080fd5b50356001600160a01b0316610fb3565b6104e46004803603602081101561058657600080fd5b50356001600160a01b031661100f565b6104bc600480360360208110156105ac57600080fd5b5035151561102a565b6104bc600480360360408110156105cb57600080fd5b506001600160a01b03813516906020013515156110a4565b6105eb611110565b604080516001600160a01b039092168252519081900360200190f35b6104e4611124565b6105eb61112a565b6104bc611139565b61062761114b565b604080519115158252519081900360200190f35b6104e46004803603602081101561065157600080fd5b50356001600160a01b0316611154565b6104bc611166565b6105eb6112e6565b6104e46004803603602081101561068757600080fd5b50356001600160a01b03166112fa565b6104bc600480360360208110156106ad57600080fd5b503561130c565b6104bc600480360360208110156106ca57600080fd5b503561169a565b6104e4600480360360208110156106e757600080fd5b50356001600160a01b0316611726565b6104e4611871565b6104e46118fb565b6106276004803603602081101561071d57600080fd5b50356001600160a01b0316611901565b6104bc611916565b6104e46004803603602081101561074b57600080fd5b50356001600160a01b0316611a96565b6104e4611ab1565b6104bc6004803603604081101561077957600080fd5b506001600160a01b0381351690602001351515611ab7565b6104bc611bd2565b6105eb61202f565b61062761203e565b6104bc600480360360408110156107bf57600080fd5b506001600160a01b0381351690602001351515612047565b6104e46120b3565b6105eb6120b9565b6106276120c8565b6104e46120d1565b6104bc6004803603602081101561080d57600080fd5b50356001600160a01b03166120d7565b6104e461224a565b6104bc612250565b6105eb612302565b6104e46004803603602081101561084b57600080fd5b50356001600160a01b0316612311565b6105eb612323565b6104bc600480360360e081101561087957600080fd5b506001600160a01b03813581169160208101358216916040820135811691606081013582169160808201359160a08101359160c09091013516612332565b6104bc600480360360608110156108cd57600080fd5b508035906020810135906040013515156124ee565b6105eb612557565b6105eb612566565b6104bc612575565b6104e46004803603602081101561091057600080fd5b50356001600160a01b0316612631565b6104e461263c565b610627612642565b6104bc6004803603606081101561094657600080fd5b508035906020810135906040013561264b565b6104bc600480360360e081101561096f57600080fd5b5080351515906020810135151590604081013590606081013590608081013515159060a081013515159060c001351515612c3f565b6104e4600480360360208110156109ba57600080fd5b50356001600160a01b0316612d0f565b6105eb612d2a565b6104e4612d39565b6104e4612d3f565b6104e4612d45565b6104e460048036036020811015610a0057600080fd5b50356001600160a01b0316612d4b565b6104e460048036036020811015610a2657600080fd5b50356001600160a01b0316612d51565b61062760048036036040811015610a4c57600080fd5b506001600160a01b0381358116916020013516612e97565b610627612eb7565b610627612ec0565b6104bc60048036036020811015610a8a57600080fd5b5035612ed0565b610627612fa7565b6104bc612fd3565b6104e461306d565b6105eb60048036036020811015610abf57600080fd5b50356001600160a01b0316613073565b6104bc60048036036020811015610ae557600080fd5b50356001600160a01b031661308e565b6104bc60048036036020811015610b0b57600080fd5b50356001600160a01b0316613217565b6104bc60048036036020811015610b3157600080fd5b50356001600160a01b0316613336565b6106276136ec565b6105eb6136f5565b61062760048036036020811015610b6757600080fd5b50356001600160a01b0316613704565b6104e4613719565b610627613764565b6104e4613774565b6104bc60048036036020811015610ba557600080fd5b50356001600160a01b031661377a565b6104bc600480360360e0811015610bcb57600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135821691608082013581169160a081013582169160c0909101351661381f565b6104bc613914565b6104e4613977565b61062760048036036020811015610c3357600080fd5b50356001600160a01b031661397d565b6001600160a01b03821615801590610c5b5750600081115b610c9d576040805162461bcd60e51b815260206004820152600e60248201526d496e76616c696420706172616d7360901b604482015290519081900360640190fd5b6001600160a01b038281166000908152607260205260409020541615610cdc576001600160a01b03918216600090815260726020526040902054909116905b6058546001600160a01b0316331480610cff57506066546001600160a01b031633145b80610d1457506067546001600160a01b031633145b80610d2e57503360009081526073602052604090205460ff165b80610d4857503360009081526074602052604090205460ff165b610d8b576040805162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015290519081900360640190fd5b610d9481613992565b6077549091506001600160a01b031615610e2757607754603e54604080516352a31c0760e01b81526001600160a01b038681166004830152336024830152604482018690526064820193909352905191909216916352a31c0791608480830192600092919082900301818387803b158015610e0e57600080fd5b505af1158015610e22573d6000803e3d6000fd5b505050505b604080516001600160a01b038416815260208101839052338183015290517fb43a20c9abfed93eb48264a3acf807336352ba8cb6ee42c1754b1b1b280a20b99181900360600190a15050565b604c6020526000908152604090205481565b6000610e9082613a1b565b90505b919050565b6001600160a01b038116610ef3576040805162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015290519081900360640190fd5b603454600160a01b900460ff1615610f3c5760405162461bcd60e51b81526004018080602001828103825260298152602001806149f56029913960400191505060405180910390fd5b6034805460ff60a01b1916600160a01b179055603380546001600160a01b0383166001600160a01b031990911681179091556040805160008152602081019290925280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a150565b60465481565b610fbb613b06565b603480546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229181900360200190a150565b6001600160a01b031660009081526056602052604090205490565b611032613b06565b60385460ff1615158115151415611048576110a1565b6038805460ff1916821515179081905560ff161561106557426037555b6038546040805160ff90921615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec59181900360200190a15b50565b6110ac613b06565b6001600160a01b038216600081815260736020908152604091829020805460ff191685151590811790915582519384529083015280517fd2a8401466e7483577592b4b5160af1ba59060100f12387853477637096cfb919281900390910190a15050565b605b5461010090046001600160a01b031681565b603f5481565b6066546001600160a01b031681565b611141613b06565b611149613b4f565b565b604a5460ff1681565b60556020526000908152604090205481565b60385460ff16156111a85760405162461bcd60e51b815260040180806020018281038252603c815260200180614bc6603c913960400191505060405180910390fd5b3360009081526054602052604090205460ff166111f65760405162461bcd60e51b815260040180806020018281038252602a815260200180614a47602a913960400191505060405180910390fd5b60415461120a90429063ffffffff613e2c16565b33600090815260536020526040902054106112565760405162461bcd60e51b8152600401808060200182810382526029815260200180614a1e6029913960400191505060405180910390fd5b336000818152605460209081526040808320805460ff1916905560559091529020546039549091611297916001600160a01b0316908363ffffffff613e8e16565b336000818152605560209081526040808320929092558151928352820183905280517f0f5bb82176feb1b5e747e28471aa92156a04d9f3ab9f45f28e2d704232b93f759281900390910190a150565b60385461010090046001600160a01b031681565b60536020526000908152604090205481565b60385460ff161561134e5760405162461bcd60e51b815260040180806020018281038252603c815260200180614bc6603c913960400191505060405180910390fd5b60008111611396576040805162461bcd60e51b815260206004820152601060248201526f043616e6e6f7420756e7374616b6520360841b604482015290519081900360640190fd5b336000908152605660205260409020548111156113e45760405162461bcd60e51b8152600401808060200182810382526024815260200180614c026024913960400191505060405180910390fd5b3360009081526054602052604090205460ff16156114335760405162461bcd60e51b815260040180806020018281038252602e815260200180614b5a602e913960400191505060405180910390fd5b600061143e33613ee5565b111561144d5761144d33613f34565b33600090815260536020908152604080832042905560549091529020805460ff19166001179055604d54611487908263ffffffff613e2c16565b604d5533600090815260556020908152604080832084905560569091529020546114b7908263ffffffff613e2c16565b33600090815260566020526040902081905561162957603854604080516334c78ae560e11b8152336004820152905160009261010090046001600160a01b03169163698f15ca916024808301926020929190829003018186803b15801561151d57600080fd5b505afa158015611531573d6000803e3d6000fd5b505050506040513d602081101561154757600080fd5b5051111561162957603854604080516334c78ae560e11b815233600482015290516101009092046001600160a01b031691635817d04291839163698f15ca91602480820192602092909190829003018186803b1580156115a657600080fd5b505afa1580156115ba573d6000803e3d6000fd5b505050506040513d60208110156115d057600080fd5b5051604080516001600160e01b031960e085901b168152600481019290925251602480830192600092919082900301818387803b15801561161057600080fd5b505af1158015611624573d6000803e3d6000fd5b505050505b604154336000818152605360205260409020547f30797de805f090008d8b19fa0c6f92d0f164789f64d6f7a1b097fbf0b1abac6b9261166e919063ffffffff6142b016565b604080516001600160a01b0390931683526020830191909152818101849052519081900360600190a150565b6116a2613b06565b614650603f540381116116eb576040805162461bcd60e51b815260206004820152600c60248201526b546f6f20666172206261636b60a01b604482015290519081900360640190fd5b603f8190556040805182815290517fd1956985dae3dbe5da7d4db0d0abc90d01284cf79627ffef5538d2cd006901049181900360200190a150565b6077546000906001600160a01b0316158015906117b95750607760009054906101000a90046001600160a01b03166001600160a01b0316635bd90b486040518163ffffffff1660e01b815260040160206040518083038186803b15801561178c57600080fd5b505afa1580156117a0573d6000803e3d6000fd5b505050506040513d60208110156117b657600080fd5b50515b15610e9357607754603e5460408051638d61c38b60e01b81526001600160a01b03868116600483015260001990930160248201529051610e9093670de0b6b3a76400009361186593911691638d61c38b91604480820192602092909190829003018186803b15801561182a57600080fd5b505afa15801561183e573d6000803e3d6000fd5b505050506040513d602081101561185457600080fd5b50516047549063ffffffff61430a16565b9063ffffffff61436316565b603954605b54604080516370a0823160e01b81526101009092046001600160a01b039081166004840152905160009391909116916370a08231916024808301926020929190829003018186803b1580156118ca57600080fd5b505afa1580156118de573d6000803e3d6000fd5b505050506040513d60208110156118f457600080fd5b5051905090565b60795481565b60736020526000908152604090205460ff1681565b60385460ff16156119585760405162461bcd60e51b815260040180806020018281038252603c815260200180614bc6603c913960400191505060405180910390fd5b3360009081526054602052604090205460ff166119bc576040805162461bcd60e51b815260206004820152601860248201527f4163636f756e74206973206e6f7420756e7374616b696e670000000000000000604482015290519081900360640190fd5b6119c5336143cd565b60006119d033613ee5565b11156119df576119df33613f34565b336000908152605460209081526040808320805460ff191690556055909152902054604d54611a139163ffffffff6142b016565b604d5533600090815260556020908152604080832054605690925290912054611a419163ffffffff6142b016565b336000818152605660209081526040808320949094556055815283822091909155825191825291517f725ee3b9a70aadcb1e002c94935880d7f515620783a5144c90e39201dc6f92da929181900390910190a1565b6001600160a01b031660009081526057602052604090205490565b60475481565b60385460ff1615611af95760405162461bcd60e51b815260040180806020018281038252603c815260200180614bc6603c913960400191505060405180910390fd5b6001600160a01b03821615801590611b1a57506001600160a01b0382163314155b611b5d576040805162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015290519081900360640190fd5b3360008181526070602090815260408083206001600160a01b03871680855290835292819020805486151560ff19909116811790915581519485529184019290925282820152517fc939ba7d9b3e1a4e6505db209888366a551f46a85918944eb89becb92289935b9181900360600190a15050565b603580546001019081905560385460ff1615611c1f5760405162461bcd60e51b815260040180806020018281038252603c815260200180614bc6603c913960400191505060405180910390fd5b600060425411611c76576040805162461bcd60e51b815260206004820152601e60248201527f5374616b696e6720706572696f6420686173206e6f7420737461727465640000604482015290519081900360640190fd5b604054603f54611c8b9163ffffffff6142b016565b421015611cc95760405162461bcd60e51b8152600401808060200182810382526039815260200180614aef6039913960400191505060405180910390fd5b607854600160a81b900460ff1615611d1c576040805162461bcd60e51b8152602060048201526011602482015270436c6f73696e67496e50726f677265737360781b604482015290519081900360640190fd5b603860019054906101000a90046001600160a01b03166001600160a01b031663acfabbe46040518163ffffffff1660e01b8152600401602060405180830381600087803b158015611d6c57600080fd5b505af1158015611d80573d6000803e3d6000fd5b505050506040513d6020811015611d9657600080fd5b505042603f5560385460408051635d13850560e01b815290516101009092046001600160a01b031691635d13850591600480820192602092909190829003018186803b158015611de557600080fd5b505afa158015611df9573d6000803e3d6000fd5b505050506040513d6020811015611e0f57600080fd5b5051603e55603854604080516347d3681760e11b81529051611f0c9261010090046001600160a01b031691638fa6d02e916004808301926020929190829003018186803b158015611e5f57600080fd5b505afa158015611e73573d6000803e3d6000fd5b505050506040513d6020811015611e8957600080fd5b50516038546040805163b9d1c70b60e01b815290516101009092046001600160a01b03169163b9d1c70b91600480820192602092909190829003018186803b158015611ed457600080fd5b505afa158015611ee8573d6000803e3d6000fd5b505050506040513d6020811015611efe57600080fd5b50519063ffffffff613e2c16565b606355604654604355603a54604080516370a0823160e01b815230600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015611f6057600080fd5b505afa158015611f74573d6000803e3d6000fd5b505050506040513d6020811015611f8a57600080fd5b5051604455604d54606255607a5460ff1615611fa857611fa8613b4f565b7f80827f48a8070d07af7887688320aadf44499e3a2751fc41cc965870cf0627d7603e54603f54604051808381526020018281526020019250505060405180910390a160355481146110a1576040805162461bcd60e51b815260206004820152601f60248201526000805160206149a0833981519152604482015290519081900360640190fd5b6034546001600160a01b031681565b60455460ff1681565b61204f613b06565b6001600160a01b038216600081815260746020908152604091829020805460ff191685151590811790915582519384529083015280517fcf84063977a2a7766d440ee9919a260c5e0add05c19db1f47b31250b89c73e399281900390910190a15050565b604d5490565b6058546001600160a01b031681565b60385460ff1681565b60625481565b603580546001019081905560385460ff16156121245760405162461bcd60e51b815260040180806020018281038252603c815260200180614bc6603c913960400191505060405180910390fd5b6001600160a01b0382161580159061214557506001600160a01b0382163314155b612188576040805162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015290519081900360640190fd5b6001600160a01b038216600090815260706020908152604080832033845290915290205460ff166121f9576040805162461bcd60e51b815260206004820152601660248201527521b0b73737ba1031b630b4b69037b7103132b430b63360511b604482015290519081900360640190fd5b61220282613f34565b6035548114612246576040805162461bcd60e51b815260206004820152601f60248201526000805160206149a0833981519152604482015290519081900360640190fd5b5050565b60405481565b612258613b06565b604254156122ad576040805162461bcd60e51b815260206004820152601b60248201527f5374616b696e672068617320616c726561647920737461727465640000000000604482015290519081900360640190fd5b4260428190556000603e819055603f9190915560518190556052819055604d819055604e819055604f8190556040517f7c01398e484f9a82feaa276906d5d1f84867a0ff5a5bd9a485d4357f58d401839190a1565b603a546001600160a01b031681565b604b6020526000908152604090205481565b6077546001600160a01b031681565b600054610100900460ff168061234b575061234b614551565b80612359575060005460ff16155b6123945760405162461bcd60e51b815260040180806020018281038252602e815260200180614ac1602e913960400191505060405180910390fd5b600054610100900460ff161580156123bf576000805460ff1961ff0019909116610100171660011790555b6123c888610e98565b6123d0613914565b60388054610100600160a81b0319166101006001600160a01b038a811691820292909217909255603980546001600160a01b03199081168a84161791829055603a80549091168984161790556040805163095ea7b360e01b8152600481019490945260001960248501525191169163095ea7b39160448083019260209291908290030181600087803b15801561246557600080fd5b505af1158015612479573d6000803e3d6000fd5b505050506040513d602081101561248f57600080fd5b505060408490556041839055690ed2b525841adfc00000604655690472698b413b43200000604755603b80546001600160a01b0319166001600160a01b03841617905580156124e4576000805461ff00191690555b5050505050505050565b6124f6613b06565b60468390556047829055605b805482151560ff199091168117909155604080518581526020810185905280820192909252517ff2192442b5560227e5c603bd8ec631a14b2fe42f35cf4e8e2083502de9571bb49181900360600190a1505050565b6039546001600160a01b031681565b603d546001600160a01b031681565b6034546001600160a01b031633146125be5760405162461bcd60e51b81526004018080602001828103825260358152602001806149c06035913960400191505060405180910390fd5b603354603454604080516001600160a01b03938416815292909116602083015280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a160348054603380546001600160a01b03199081166001600160a01b03841617909155169055565b6000610e9082613ee5565b603e5481565b607a5460ff1681565b6035805460010190819055607854600160a01b900460ff16612bac576065546040805163bf40fac160e01b8152602060048201819052601360248301527221b937b9b9a1b430b4b721b7b63632b1ba37b960691b604483015291516001600160a01b039093169263bf40fac192606480840193919291829003018186803b1580156126d557600080fd5b505afa1580156126e9573d6000803e3d6000fd5b505050506040513d60208110156126ff57600080fd5b50516001600160a01b031633148061272157506033546001600160a01b031633145b61275c576040805162461bcd60e51b81526020600482015260076024820152660496e76434349560cc1b604482015290519081900360640190fd5b607854600160a81b900460ff166127ad576040805162461bcd60e51b815260206004820152601060248201526f139bdd125b90db1bdcd954195c9a5bd960821b604482015290519081900360640190fd5b60465484111580156127c157506046548311155b80156127d257506046546005028211155b61280d5760405162461bcd60e51b8152600401808060200182810382526021815260200180614c8b6021913960400191505060405180910390fd5b6065546040805163045f670760e21b8152602060048201819052600d60248301526c29b0b332a137bc213ab33332b960991b604483015291516000936001600160a01b03169263117d9c1c9260648082019391829003018186803b15801561287457600080fd5b505afa158015612888573d6000803e3d6000fd5b505050506040513d602081101561289e57600080fd5b5051603a54604080516370a0823160e01b8152306004820152905192935060009283926001600160a01b0316916370a08231916024808301926020929190829003018186803b1580156128f057600080fd5b505afa158015612904573d6000803e3d6000fd5b505050506040513d602081101561291a57600080fd5b5051905061292785614557565b6044558215612b69576065546040805163bf40fac160e01b8152602060048201819052600d60248301526c29b0b332a137bc213ab33332b960991b604483015291516000936001600160a01b03169263bf40fac19260648082019391829003018186803b15801561299757600080fd5b505afa1580156129ab573d6000803e3d6000fd5b505050506040513d60208110156129c157600080fd5b5051604454909150821015612ac857604454603a54604080516370a0823160e01b81526001600160a01b0385811660048301529151938690039391909216916370a08231916024808301926020929190829003018186803b158015612a2557600080fd5b505afa158015612a39573d6000803e3d6000fd5b505050506040513d6020811015612a4f57600080fd5b50511015612a605760019250612ac3565b806001600160a01b0316639ffcb31683604454036040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015612aaa57600080fd5b505af1158015612abe573d6000803e3d6000fd5b505050505b612b67565b6000604454118015612adb575081604454105b15612b6757603a54604480546040805163a9059cbb60e01b81526001600160a01b03868116600483015292870360248201529051919093169263a9059cbb92818101926020929091908290030181600087803b158015612b3a57600080fd5b505af1158015612b4e573d6000803e3d6000fd5b505050506040513d6020811015612b6457600080fd5b50505b505b604387905560478690556078805460ff60a81b191690556037546079541415612ba857821580612b965750815b6038805460ff19169115159190911790555b5050505b7fb4873f5e95851bc84e2c197ca35129e61b53e3525c5d563b4dfd9307833f4dcc8484612bd885614557565b60408051938452602084019290925282820152519081900360600190a16035548114612c39576040805162461bcd60e51b815260206004820152601f60248201526000805160206149a0833981519152604482015290519081900360640190fd5b50505050565b612c47613b06565b604a805488151560ff1991821681179092556045805489151590831681179091556040888155604188905560718054881515908516811790915560788054881515600160a01b810260ff60a01b1990921691909117909155607a8054881515961686179055825195865260208601939093528482018a905260608501899052608085015260a084019190915260c0830191909152517fd0b7c05d30d50a3a23a9835892652aebc30da318b53c90521825ea7698e590a09181900360e00190a150505050505050565b6001600160a01b03166000908152604b602052604090205490565b6033546001600160a01b031681565b60375481565b60415481565b60635481565b50600090565b603e546001600160a01b03821660009081526061602052604081205490911480612d9157506001600160a01b038216600090815260566020526040902054155b80612db55750603e546001600160a01b038316600090815260576020526040902054145b80612dc05750606254155b610e9357610e90612dde6063546062546142b090919063ffffffff16565b604354603854604080516317640e0760e01b81526001600160a01b03888116600483015291516118659493612e8b9361010090910416916317640e07916024808301926020929190829003018186803b158015612e3a57600080fd5b505afa158015612e4e573d6000803e3d6000fd5b505050506040513d6020811015612e6457600080fd5b50516001600160a01b0388166000908152605660205260409020549063ffffffff6142b016565b9063ffffffff61430a16565b607060209081526000928352604080842090915290825290205460ff1681565b605b5460ff1681565b607854600160a01b900460ff1681565b603580546001019081905560385460ff1615612f1d5760405162461bcd60e51b815260040180806020018281038252603c815260200180614bc6603c913960400191505060405180910390fd5b612f288233336145e1565b604080513381526020810184905281517f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d929181900390910190a16035548114612246576040805162461bcd60e51b815260206004820152601f60248201526000805160206149a0833981519152604482015290519081900360640190fd5b600080604254118015612fce5750604054603f54612fca9163ffffffff6142b016565b4210155b905090565b603580546001019081905560385460ff16156130205760405162461bcd60e51b815260040180806020018281038252603c815260200180614bc6603c913960400191505060405180910390fd5b61302933613f34565b60355481146110a1576040805162461bcd60e51b815260206004820152601f60248201526000805160206149a0833981519152604482015290519081900360640190fd5b60445481565b6072602052600090815260409020546001600160a01b031681565b613096613b06565b60385461010090046001600160a01b031615613139576039546038546040805163095ea7b360e01b81526101009092046001600160a01b039081166004840152600060248401819052915193169263095ea7b3926044808201936020939283900390910190829087803b15801561310c57600080fd5b505af1158015613120573d6000803e3d6000fd5b505050506040513d602081101561313657600080fd5b50505b60388054610100600160a81b0319166101006001600160a01b03848116918202929092179092556039546040805163095ea7b360e01b8152600481019490945260001960248501525191169163095ea7b39160448083019260209291908290030181600087803b1580156131ac57600080fd5b505af11580156131c0573d6000803e3d6000fd5b505050506040513d60208110156131d657600080fd5b5050604080516001600160a01b038316815290517feb1a4b1e230d212e1644ea31e3890084e2fa17ddee990e46a46e198e1728c4a09181900360200190a150565b61321f613b06565b6001600160a01b03811661326c576040805162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015290519081900360640190fd5b603454600160a81b900460ff16156132c1576040805162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481d1c985b9cd9995c9c9959606a1b604482015290519081900360640190fd5b603380546001600160a01b038084166001600160a01b03199092168217928390556034805460ff60a81b1916600160a81b17905560408051939091168352602083019190915280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a150565b60385460ff16156133785760405162461bcd60e51b815260040180806020018281038252603c815260200180614bc6603c913960400191505060405180910390fd5b60715460ff166133cf576040805162461bcd60e51b815260206004820152601960248201527f4d65726765206163636f756e742069732064697361626c656400000000000000604482015290519081900360640190fd5b6001600160a01b038116158015906133f057506001600160a01b0381163314155b613433576040805162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015290519081900360640190fd5b61343c33613ee5565b15801561344f575061344d81613ee5565b155b61348a5760405162461bcd60e51b815260040180806020018281038252603b815260200180614c26603b913960400191505060405180910390fd5b3360009081526054602052604090205460ff161580156134c357506001600160a01b03811660009081526054602052604090205460ff16155b6134fe5760405162461bcd60e51b815260040180806020018281038252603e815260200180614b88603e913960400191505060405180910390fd5b60385460408051630282a2ed60e21b81523360048201526001600160a01b038481166024830152915161010090930490911691630a0a8bb49160448082019260009290919082900301818387803b15801561355857600080fd5b505af115801561356c573d6000803e3d6000fd5b505033600090815260566020526040808220546001600160a01b03861683529120546135a09350915063ffffffff6142b016565b6001600160a01b038216600081815260566020908152604080832094909455338252604b90528281205491815291909120546135e19163ffffffff6142b016565b6001600160a01b0382166000818152604b6020908152604080832094909455338252604c90528281205491815291909120546136229163ffffffff6142b016565b6001600160a01b0382166000818152604c6020818152604080842095909555603e546057808352868520829055606180845287862092909255338086526053845287862086905560548452878620805460ff191690556055845287862086905560568452878620869055604b8452878620869055938352868520859055825285842084905581528483209290925583519081529081019190915281517fa0fc26d627101bedf9c6cedb33e9eeac3fa2a7d508f89b597134bcee1a12d32c929181900390910190a150565b60715460ff1681565b6067546001600160a01b031681565b60546020526000908152604090205460ff1681565b603a54604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b1580156118ca57600080fd5b607854600160a81b900460ff1681565b60435481565b60385460ff16156137bc5760405162461bcd60e51b815260040180806020018281038252603c815260200180614bc6603c913960400191505060405180910390fd5b3360009081526072602090815260409182902080546001600160a01b0319166001600160a01b038516908117909155825190815291517f0c417702befaa0d74611c15e4278a897f344514ffbfbd4ea9a6e9168be46b8da9281900390910190a150565b613827613b06565b605880546001600160a01b03808a166001600160a01b03199283168117909355606680548a83169084168117909155606780548a84169085168117909155603d80548a85169086168117909155605b80548a86166101008102610100600160a81b031990921691909117909155606580548a8716908816811790915560778054968a16969097168617909655604080519788526020880194909452868401929092526060860152608085015260a084019290925260c0830152517fbe8209a2817cacf2137f586f29208a496d2d159efa011f3937e8172892826a9a9181900360e00190a150505050505050565b60365460ff1615613962576040805162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b604482015290519081900360640190fd5b6036805460ff19166001908117909155603555565b60425481565b60746020526000908152604090205460ff1681565b603a546040805163313ce56760e01b815290516000926001600160a01b03169163313ce567916004808301926020929190829003018186803b1580156139d757600080fd5b505afa1580156139eb573d6000803e3d6000fd5b505050506040513d6020811015613a0157600080fd5b5051600614613a105781610e90565b5064e8d4a510000290565b600080613a2783612d51565b905080613a38576000915050610e93565b613aff613a526063546062546142b090919063ffffffff16565b604454603854604080516317640e0760e01b81526001600160a01b03898116600483015291516118659493612e8b9361010090910416916317640e07916024808301926020929190829003018186803b158015613aae57600080fd5b505afa158015613ac2573d6000803e3d6000fd5b505050506040513d6020811015613ad857600080fd5b50516001600160a01b0389166000908152605660205260409020549063ffffffff6142b016565b9392505050565b6033546001600160a01b031633146111495760405162461bcd60e51b815260040180806020018281038252602f815260200180614a71602f913960400191505060405180910390fd5b6065546040805163045f670760e21b8152602060048201819052601360248301527221b937b9b9a1b430b4b721b7b63632b1ba37b960691b604483015291516001600160a01b039093169263117d9c1c92606480840193919291829003018186803b158015613bbd57600080fd5b505afa158015613bd1573d6000803e3d6000fd5b505050506040513d6020811015613be757600080fd5b50511561114957607854600160a01b900460ff16613c29576038805460ff191660011790556078805460ff60a81b1916600160a81b1790554260378190556079555b6065546040805163bf40fac160e01b8152602060048201819052601360248301527221b937b9b9a1b430b4b721b7b63632b1ba37b960691b604483015291516001600160a01b039093169263bf40fac192606480840193919291829003018186803b158015613c9757600080fd5b505afa158015613cab573d6000803e3d6000fd5b505050506040513d6020811015613cc157600080fd5b5051606254606354607754603e546040805163df022bf560e01b81526000199092016004830152516001600160a01b03958616956334bd229c959493169163df022bf5916024808301926020929190829003018186803b158015613d2457600080fd5b505afa158015613d38573d6000803e3d6000fd5b505050506040513d6020811015613d4e57600080fd5b5051603a54604080516370a0823160e01b81523060048201529051613dcd926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015613d9c57600080fd5b505afa158015613db0573d6000803e3d6000fd5b505050506040513d6020811015613dc657600080fd5b5051613992565b6040518563ffffffff1660e01b815260040180858152602001848152602001838152602001828152602001945050505050600060405180830381600087803b158015613e1857600080fd5b505af1158015612c39573d6000803e3d6000fd5b600082821115613e83576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052613ee0908490614787565b505050565b600080613ef183612d51565b905080613f02576000915050610e93565b605b5460ff16613f13579050610e93565b613f2c613f1f84611726565b829063ffffffff6142b016565b915050610e93565b60385460ff1615613f765760405162461bcd60e51b815260040180806020018281038252603c815260200180614bc6603c913960400191505060405180910390fd5b604a5460ff16613fcd576040805162461bcd60e51b815260206004820152601860248201527f436c61696d696e67206973206e6f7420656e61626c65642e0000000000000000604482015290519081900360640190fd5b600060425411614024576040805162461bcd60e51b815260206004820152601e60248201527f5374616b696e6720706572696f6420686173206e6f7420737461727465640000604482015290519081900360640190fd5b603e546001600160a01b03821660009081526057602052604090205410614084576040805162461bcd60e51b815260206004820152600f60248201526e105b1c9958591e4818db185a5b5959608a1b604482015290519081900360640190fd5b60455460ff161561415e57600061409a82613a1b565b9050801561415c57603a546140bf906001600160a01b0316838363ffffffff613e8e16565b6001600160a01b0382166000908152604c60205260409020546140e8908263ffffffff6142b016565b6001600160a01b0383166000908152604c6020526040902055605254614114908263ffffffff6142b016565b605255604080516001600160a01b03841681526020810183905281517f5b16e1043a283423361eb77682c99aff55948b34296846800a1a7dc9547a89fc929181900390910190a15b505b600061416982613ee5565b9050801561429057605b546040805163b01ca88f60e01b81526001600160a01b0385811660048301526024820185905291516101009093049091169163b01ca88f9160448082019260009290919082900301818387803b1580156141cc57600080fd5b505af11580156141e0573d6000803e3d6000fd5b5050506001600160a01b0383166000908152604b602052604090205461420d91508263ffffffff6142b016565b6001600160a01b0383166000908152604b6020526040902055605154614239908263ffffffff6142b016565b6051557fdacbdde355ba930696a362ea6738feb9f8bd52dfb3d81947558fd3217e23e325828261426882612d51565b604080516001600160a01b039094168452602084019290925282820152519081900360600190a15b50603e546001600160a01b03909116600090815260576020526040902055565b600082820183811015613aff576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008261431957506000613e88565b8282028284828161432657fe5b0414613aff5760405162461bcd60e51b8152600401808060200182810382526021815260200180614aa06021913960400191505060405180910390fd5b60008082116143b9576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b60008284816143c457fe5b04949350505050565b6001600160a01b0381166000908152605660205260409020546110a157603854604080516334c78ae560e11b81526001600160a01b038481166004830152915160009361010090049092169163698f15ca91602480820192602092909190829003018186803b15801561443f57600080fd5b505afa158015614453573d6000803e3d6000fd5b505050506040513d602081101561446957600080fd5b505111156110a157603854604080516334c78ae560e11b81526001600160a01b03848116600483015291516101009093049091169163ad6d15de91839163698f15ca91602480820192602092909190829003018186803b1580156144cc57600080fd5b505afa1580156144e0573d6000803e3d6000fd5b505050506040513d60208110156144f657600080fd5b5051604080516001600160e01b031960e085901b168152600481019290925251602480830192600092919082900301818387803b15801561453657600080fd5b505af115801561454a573d6000803e3d6000fd5b5050505050565b303b1590565b603a546040805163313ce56760e01b815290516000926001600160a01b03169163313ce567916004808301926020929190829003018186803b15801561459c57600080fd5b505afa1580156145b0573d6000803e3d6000fd5b505050506040513d60208110156145c657600080fd5b50516006146145d55781610e90565b5064e8d4a51000900490565b600060425411614638576040805162461bcd60e51b815260206004820152601e60248201527f5374616b696e6720706572696f6420686173206e6f7420737461727465640000604482015290519081900360640190fd5b6000831161467e576040805162461bcd60e51b815260206004820152600e60248201526d043616e6e6f74207374616b6520360941b604482015290519081900360640190fd5b6001600160a01b03821660009081526054602052604090205460ff16156146d65760405162461bcd60e51b8152600401808060200182810382526032815260200180614b286032913960400191505060405180910390fd5b60006146e183613ee5565b11156146f0576146f082613f34565b603e546001600160a01b038316600090815260616020526040902055614715826143cd565b604d54614728908463ffffffff6142b016565b604d556001600160a01b038216600090815260566020526040902054614754908463ffffffff6142b016565b6001600160a01b03808416600090815260566020526040902091909155603954613ee0911682308663ffffffff61493f16565b614799826001600160a01b0316614999565b6147ea576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106148285780518252601f199092019160209182019101614809565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811461488a576040519150601f19603f3d011682016040523d82523d6000602084013e61488f565b606091505b5091509150816148e6576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115612c395780806020019051602081101561490257600080fd5b5051612c395760405162461bcd60e51b815260040180806020018281038252602a815260200180614c61602a913960400191505060405180910390fd5b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052612c39908590614787565b3b15159056fe5265656e7472616e637947756172643a207265656e7472616e742063616c6c00596f75206d757374206265206e6f6d696e61746564206265666f726520796f752063616e20616363657074206f776e657273686970416c726561647920696e697469616c697a65642c20757365206e6f6d696e6174654e65774f776e657243616e6e6f7420756e7374616b65207965742c20636f6f6c646f776e206e6f7420657870697265642e4163636f756e7420686173206e6f742074726967676572656420756e7374616b6520636f6f6c646f776e4f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564412066756c6c20706572696f6420686173206e6f74207061737365642073696e636520746865206c61737420636c6f73656420706572696f64546865207374616b6572206973207061757365642066726f6d207374616b696e672064756520746f20756e7374616b696e674163636f756e742068617320616c72656164792074726967676572656420756e7374616b6520636f6f6c646f776e43616e6e6f74206d657267652c2063616e63656c20756e7374616b696e67206f6e20626f7468206163636f756e7473206265666f7265206d657267696e675468697320616374696f6e2063616e6e6f7420626520706572666f726d6564207768696c652074686520636f6e7472616374206973207061757365644163636f756e7420646f65736e7420686176652074686174206d756368207374616b656443616e6e6f74206d657267652c20636c61696d2072657761726473206f6e20626f7468206163636f756e7473206265666f7265206d657267696e675361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656452656a65637465642064756520746f20737573706963696f75732076616c756573a265627a7a723158209d97c81f95d047d4331c4ff98b17ffc12e4f8c946918ed45e316c5ce3570a39e64736f6c63430005100032

Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.