ETH Price: $3,039.34 (-0.94%)

Contract

0xE9Ec756Eb37452F3e00D0409ce96C53E97f1c286
 

Overview

ETH Balance

0 ETH

ETH Value

$0.00

Sponsored

Transaction Hash
Method
Block
From
To
Value
0x608060401140860262023-12-28 13:40:29110 days ago1703770829IN
 Create: CrossChainCollector
0 ETH0.000011660.00418759

View more zero value Internal Transactions in Advanced View mode

Advanced mode:

Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
CrossChainCollector

Compiler Version
v0.8.4+commit.c7e474f2

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 13 : CrossChainCollector.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IRouterClient} from "@chainlink/contracts-ccip/src/v0.8/ccip/interfaces/IRouterClient.sol";
import {Client} from "@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Client.sol";
// import {LinkTokenInterface} from "@chainlink/contracts/src/v0.8/shared/interfaces/LinkTokenInterface.sol";
// import {CCIPReceiver} from "@chainlink/contracts-ccip/src/v0.8/ccip/applications/CCIPReceiver.sol";

import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";

// internal
import "../utils/proxy/solidity-0.8.0/ProxyReentrancyGuard.sol";
import "../utils/proxy/solidity-0.8.0/ProxyOwned.sol";
import "../utils/proxy/solidity-0.8.0/ProxyPausable.sol";

import "../interfaces/IStakingThales.sol";
import "../interfaces/IAddressManager.sol";

import "./CCIPReceiverProxy.sol";

/// @title - Cross Chain Collector contract for Thales staking rewards
contract CrossChainCollector is Initializable, ProxyOwned, ProxyPausable, ProxyReentrancyGuard, CCIPReceiverProxy {
    // Custom errors to provide more descriptive revert messages.
    error NotEnoughBalance(uint256 currentBalance, uint256 calculatedFees); // Used to make sure contract has enough balance.

    IRouterClient private s_router;
    address private stakingThales;
    // the CrossChainCollector instance on master chain
    address public masterCollector;
    // chainID of the master chain as assigned by CCIP
    uint64 public masterCollectorChain;

    //index to chainId as assigned by CCIP
    mapping(uint => uint64) public chainSelector;
    // chainID to index above
    mapping(uint64 => uint) public chainSelectorIndex;
    // index to collector address
    mapping(uint => address) public collectorAddress;

    mapping(uint => uint) public lastPeriodForChain;

    // first uint is the CCIP period, second uint is the chain selector per CCIP convention
    mapping(uint => mapping(uint => uint)) public chainStakedAmountInPeriod;
    mapping(uint => mapping(uint => uint)) public chainEscrowedAmountInPeriod;
    mapping(uint => mapping(uint => uint)) public chainBaseRewardsInPeriod;
    mapping(uint => mapping(uint => uint)) public chainExtraRewardsInPeriod;
    mapping(uint => mapping(uint => uint)) public chainBonusPointsInPeriod;
    mapping(uint => mapping(uint => uint)) public chainRevenueInPeriod;
    mapping(uint => mapping(uint => uint)) public chainRevenueShareInPeriod;

    mapping(uint => uint) public calculatedStakedAmountForPeriod;
    mapping(uint => uint) public calculatedEscrowedAmountForPeriod;
    mapping(uint => uint) public calculatedBonusPointsForPeriod;
    mapping(uint => uint) public calculatedRevenueForPeriod;

    mapping(bytes32 => bool) public messageIdAlreadyReceived;
    mapping(uint => uint64) public messagesReceivedFromChainSelector;
    mapping(uint => bytes) public messagesReceived;
    uint public numOfMessagesReceived;

    uint public numOfActiveCollectors;
    uint public period;
    uint public baseRewardsPerPeriod;
    uint public extraRewardsPerPeriod;
    uint public collectedResultsForPeriod;
    uint private lastPeriodBeforeTesting;

    bool public readyToBroadcast;
    bool private readOnlyMode;
    uint public gasLimitUsed;
    uint public weeklyRewardsDecreaseFactor;

    IAddressManager private addressManager;

    uint private constant ONE_MILLION_GAS = 1e6;
    uint private constant MAX_GAS = 10 * ONE_MILLION_GAS;
    uint private constant ONE = 1e18;
    uint64 public localChainSelector;

    /* ========== INITIALIZERS ========== */
    function initialize(
        address _router,
        bool _masterCollector,
        uint64 _masterCollectorSelector,
        uint64 _localChainSelector
    ) public initializer {
        setOwner(msg.sender);
        initNonReentrant();
        _setRouter(_router);
        s_router = IRouterClient(_router);
        gasLimitUsed = ONE_MILLION_GAS;
        localChainSelector = _localChainSelector;
        if (_masterCollector) {
            masterCollector = address(this);
            masterCollectorChain = _masterCollectorSelector;
            chainSelector[0] = _masterCollectorSelector;
            collectorAddress[_masterCollectorSelector] = address(this);
            chainSelectorIndex[_masterCollectorSelector] = 0;
            numOfActiveCollectors = 1;
            period = 1;
        }
    }

    receive() external payable {}

    /* ========== VIEW FUNCTIONS ========== */

    /// @notice Check if this CCIP contract is a master collector CCIP contract
    function isMasterCollector() external view returns (bool isMaster) {
        isMaster = masterCollector == address(this) && localChainSelector == masterCollectorChain;
    }

    /// @notice Get the chain selector number of the last message received on contract
    function getChainSelectorForLastMessage() external view returns (uint64 chainSelector_) {
        if (numOfMessagesReceived > 0) {
            chainSelector_ = messagesReceivedFromChainSelector[numOfMessagesReceived - 1];
        }
    }

    /* ========== EXTERNAL FUNCTIONS ========== */

    /// @notice Used for sending staking information at the end of each period by the (local) Staking contract on the particular chain.
    /// @param _totalStakedLastPeriodEnd the amount of staked THALES at the end of a period
    /// @param _totalEscrowedLastPeriodEnd the amount of escrowed THALES at the end of a period
    /// @param _bonusPoints the total bonus points at the end of a period
    /// @param _revShare the total revenue at the end of a period
    function sendOnClosePeriod(
        uint _totalStakedLastPeriodEnd,
        uint _totalEscrowedLastPeriodEnd,
        uint _bonusPoints,
        uint _revShare
    ) external {
        address _stakingThales_ = addressManager.getAddress("StakingThales");
        require(msg.sender == _stakingThales_, "InvSender");
        _sendOnClosePeriod(_totalStakedLastPeriodEnd, _totalEscrowedLastPeriodEnd, _bonusPoints, _revShare);
    }

    /// @notice Only Admin function: Used for sending staking information at the end of each period by the (local) Staking contract on the particular chain.
    /// @param _totalStakedLastPeriodEnd the amount of staked THALES at the end of a period
    /// @param _totalEscrowedLastPeriodEnd the amount of escrowed THALES at the end of a period
    /// @param _bonusPoints the total bonus points at the end of a period
    /// @param _revShare the total revenue at the end of a period
    function sendOnClosePeriodAdmin(
        uint _totalStakedLastPeriodEnd,
        uint _totalEscrowedLastPeriodEnd,
        uint _bonusPoints,
        uint _revShare
    ) external onlyOwner {
        _sendOnClosePeriod(_totalStakedLastPeriodEnd, _totalEscrowedLastPeriodEnd, _bonusPoints, _revShare);
    }

    /// @notice (If it is master collector) when all messages are received from each chain, the final calculated amounts are broadcasted to all Staking contracts via CCIP
    function broadcastMessageToAll() external nonReentrant {
        require(readyToBroadcast || msg.sender == owner, "NotReadyToBroadcast");
        // the flag is true only if collectedResultsForPeriod == numOfActiveCollectors
        _broadcastMessageToAll(); // messages are broadcasted
        collectedResultsForPeriod = 0; // message counter is reset
        readyToBroadcast = false; // the broadcast flag is reset
        ++period; // the period is increased
        if (weeklyRewardsDecreaseFactor > 0) {
            // in case of dynamic decrease of rewards
            _setRewardsForNextPeriod(); // the rewards for the next period are decreased
        }
    }

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

    /// @notice function triggered by local Staking contract on close period
    function _sendOnClosePeriod(
        uint _totalStakedLastPeriodEnd,
        uint _totalEscrowedLastPeriodEnd,
        uint _bonusPoints,
        uint _revShare
    ) internal {
        if (masterCollector == address(this) && localChainSelector == masterCollectorChain) {
            _storeRewards(
                masterCollectorChain,
                _totalStakedLastPeriodEnd,
                _totalEscrowedLastPeriodEnd,
                _bonusPoints,
                _revShare
            );
            if (lastPeriodForChain[localChainSelector] < period) {
                ++collectedResultsForPeriod;
                if (collectedResultsForPeriod == numOfActiveCollectors) {
                    readyToBroadcast = true;
                }
            }
            lastPeriodForChain[localChainSelector] = period;
        } else {
            bytes memory message = abi.encode(
                _totalStakedLastPeriodEnd,
                _totalEscrowedLastPeriodEnd,
                _bonusPoints,
                _revShare
            );
            _sendMessageToChain(masterCollectorChain, message);
        }
        emit SentOnClosePeriod(_totalStakedLastPeriodEnd, _totalEscrowedLastPeriodEnd, _bonusPoints, _revShare);
    }

    /// @notice processing/handling received messages
    function _ccipReceive(Client.Any2EVMMessage memory any2EvmMessage) internal override {
        // decoding the message
        if (!messageIdAlreadyReceived[any2EvmMessage.messageId] && localChainSelector > 0) {
            // check if the particular message has been already received
            address sender = abi.decode(any2EvmMessage.sender, (address)); // get the message sender (used for further checks)
            messagesReceivedFromChainSelector[numOfMessagesReceived] = any2EvmMessage.sourceChainSelector; // store the chain selector of the message
            messagesReceived[numOfMessagesReceived] = any2EvmMessage.data; // store the message content
            messageIdAlreadyReceived[any2EvmMessage.messageId] = true; // flag the message as received
            ++numOfMessagesReceived; // increase the message counter

            if (masterCollector == address(this) && localChainSelector == masterCollectorChain) {
                uint sourceChainSelector = any2EvmMessage.sourceChainSelector; // cache the source collector
                // if the contract is master collector, use master collector mode of processing
                if (
                    collectorAddress[sourceChainSelector] == sender && lastPeriodForChain[sourceChainSelector] < period // check if the sender is registered and it is first incoming message in this period
                ) {
                    lastPeriodForChain[sourceChainSelector] = period; // set last message received in this period
                    _calculateRewards(any2EvmMessage.data, sourceChainSelector); // calculate and store the received rewards information
                    ++collectedResultsForPeriod; // increase the number of collected results
                    if (collectedResultsForPeriod == numOfActiveCollectors) {
                        // if messages are received from all collectors
                        readyToBroadcast = true; // calculated results are ready for broadcasting
                    }
                }
            } else if (
                masterCollector == sender &&
                localChainSelector != any2EvmMessage.sourceChainSelector &&
                localChainSelector != masterCollectorChain
            ) {
                // receive broadcast message from master node
                // if this contract is not a master collector
                _updateRewardsOnStakingContract(any2EvmMessage.data); // process and send incoming message to local Staking contract
            }
        }
        emit MessageReceived(
            any2EvmMessage.messageId,
            any2EvmMessage.sourceChainSelector, // fetch the source chain identifier (aka selector)
            abi.decode(any2EvmMessage.sender, (address)), // abi-decoding of the sender address,
            any2EvmMessage.data
        );
    }

    // @notice decode and store values received
    function _calculateRewards(bytes memory data, uint _chainSelector) internal {
        (uint stakedAmount, uint escrowedAmount, uint bonusPoints, uint revShare) = abi.decode(
            data,
            (uint, uint, uint, uint)
        );
        _storeRewards(_chainSelector, stakedAmount, escrowedAmount, bonusPoints, revShare);
    }

    // @notice store the rewards
    function _storeRewards(
        uint _chainSelector,
        uint _stakedAmount,
        uint _escrowedAmount,
        uint _bonusPoints,
        uint _revShare
    ) internal {
        chainStakedAmountInPeriod[period][_chainSelector] = _stakedAmount;
        chainEscrowedAmountInPeriod[period][_chainSelector] = _escrowedAmount;
        chainBonusPointsInPeriod[period][_chainSelector] = _bonusPoints;
        chainRevenueInPeriod[period][_chainSelector] = _revShare;

        calculatedStakedAmountForPeriod[period] += _stakedAmount;
        calculatedEscrowedAmountForPeriod[period] += _escrowedAmount;
        calculatedBonusPointsForPeriod[period] += _bonusPoints;
        calculatedRevenueForPeriod[period] += _revShare;
    }

    // @notice broadcast messages
    function _broadcastMessageToAll() internal {
        uint chainBaseRewards;
        uint chainExtraRewards;
        uint revShare;
        bytes memory message;

        for (uint i = 0; i < numOfActiveCollectors; i++) {
            uint64 chainId = chainSelector[i];
            chainBaseRewards =
                ((chainStakedAmountInPeriod[period][chainId] + chainEscrowedAmountInPeriod[period][chainId]) *
                    baseRewardsPerPeriod) /
                (calculatedStakedAmountForPeriod[period] + calculatedEscrowedAmountForPeriod[period]);

            chainExtraRewards =
                (chainBonusPointsInPeriod[period][chainId] * extraRewardsPerPeriod) /
                (calculatedBonusPointsForPeriod[period]);

            revShare =
                ((chainStakedAmountInPeriod[period][chainId] + chainEscrowedAmountInPeriod[period][chainId]) *
                    calculatedRevenueForPeriod[period]) /
                (calculatedStakedAmountForPeriod[period] + calculatedEscrowedAmountForPeriod[period]);

            chainBaseRewardsInPeriod[period][chainId] = chainBaseRewards;
            chainExtraRewardsInPeriod[period][chainId] = chainExtraRewards;
            chainRevenueShareInPeriod[period][chainId] = revShare;

            message = abi.encode(chainBaseRewards, chainExtraRewards, revShare);
            // 0 index is master
            if (masterCollectorChain == chainId) {
                _updateRewards(chainBaseRewards, chainExtraRewards, revShare);
            } else {
                _sendMessageToChain(chainId, message);
            }
        }
    }

    function _sendMessageToChain(uint64 _chainSelector, bytes memory _message) internal returns (bytes32 messageId) {
        Client.EVM2AnyMessage memory evm2AnyMessage = Client.EVM2AnyMessage({
            receiver: abi.encode(collectorAddress[_chainSelector]), // ABI-encoded receiver address
            data: _message, // ABI-encoded string
            tokenAmounts: new Client.EVMTokenAmount[](0), // Empty array indicating no tokens are being sent
            extraArgs: Client._argsToBytes(
                // Additional arguments, setting gas limit and non-strict sequencing mode
                Client.EVMExtraArgsV1({gasLimit: gasLimitUsed, strict: false})
            ),
            // Set the feeToken  address, indicating LINK will be used for fees
            feeToken: address(0)
        });

        // Get the fee required to send the message
        uint256 fees = s_router.getFee(_chainSelector, evm2AnyMessage);

        if (fees > address(this).balance) revert NotEnoughBalance(address(this).balance, fees);

        // Send the message through the router and store the returned message ID
        messageId = s_router.ccipSend{value: fees}(_chainSelector, evm2AnyMessage);

        // Emit an event with message details
        emit MessageSent(messageId, _chainSelector, collectorAddress[_chainSelector], _message, address(0), fees);

        // Return the message ID
        return messageId;
    }

    function _updateRewardsOnStakingContract(bytes memory data) internal {
        (uint baseRewards, uint extraRewards, uint revShare) = abi.decode(data, (uint, uint, uint));
        _updateRewards(baseRewards, extraRewards, revShare);
    }

    function _updateRewards(
        uint _baseRewards,
        uint _extraRewards,
        uint _revShare
    ) internal {
        IStakingThales _stakingThales_ = IStakingThales(addressManager.getAddress("StakingThales"));
        _stakingThales_.updateStakingRewards(_baseRewards, _extraRewards, _revShare);
    }

    function _setRewardsForNextPeriod() internal {
        baseRewardsPerPeriod = (baseRewardsPerPeriod * weeklyRewardsDecreaseFactor) / ONE;
        extraRewardsPerPeriod = (extraRewardsPerPeriod * weeklyRewardsDecreaseFactor) / ONE;
    }

    /* ========== CONTRACT SETTERS FUNCTIONS ========== */

    /// @notice Set address manager on contract
    /// @param _addressManager address of Address Manager contract
    function setAddressManager(address _addressManager) external onlyOwner {
        addressManager = IAddressManager(_addressManager);
        emit SetAddressManager(_addressManager);
    }

    /// @notice Set CCIP router per chain
    /// @param _router address of CCIP Router contract
    function setCCIPRouter(address _router) external onlyOwner {
        _setRouter(_router);
        s_router = IRouterClient(_router);
        emit SetCCIPRouter(_router);
    }

    /// @notice Set CCIP router per chain
    /// @param _baseRewardsPerPeriod base rewards per period
    /// @param _extraRewardsPerPeriod extra rewards per period
    /// @param _weeklyDecreaseFactor weekly decrease factor in (X * 1e16, where X is percentage - e.g. 5% = 5*1e16)
    function setPeriodRewards(
        uint _baseRewardsPerPeriod,
        uint _extraRewardsPerPeriod,
        uint _weeklyDecreaseFactor
    ) external onlyOwner {
        baseRewardsPerPeriod = _baseRewardsPerPeriod;
        extraRewardsPerPeriod = _extraRewardsPerPeriod;
        weeklyRewardsDecreaseFactor = _weeklyDecreaseFactor;
        emit SetPeriodRewards(_baseRewardsPerPeriod, _extraRewardsPerPeriod, _weeklyDecreaseFactor);
    }

    /// @notice Set gas limit to be used for for cross message
    /// @param _gasLimitUsed gas limit
    function setGasLimit(uint _gasLimitUsed) external onlyOwner {
        require(_gasLimitUsed <= MAX_GAS, "Exceeds MAX_GAS");
        gasLimitUsed = _gasLimitUsed;
        emit SetGasLimit(_gasLimitUsed);
    }

    /// @notice Set master collector address and selector
    /// @param _masterCollector address of the master collector
    /// @param _materCollectorChainId Chainlink predefined selector per chain
    function setMasterCollector(
        address _masterCollector,
        uint64 _materCollectorChainId,
        uint64 _localChainSelector
    ) external onlyOwner {
        localChainSelector = _localChainSelector;
        masterCollector = _masterCollector;
        masterCollectorChain = _materCollectorChainId;
        collectorAddress[_materCollectorChainId] = _masterCollector;
        chainSelector[0] = _materCollectorChainId;
        chainSelectorIndex[_materCollectorChainId] = 0;
        numOfActiveCollectors = numOfActiveCollectors == 0 ? 1 : numOfActiveCollectors;
        emit MasterCollectorSet(_masterCollector, _materCollectorChainId);
    }

    /// @notice (ONLY in Master collector): Add a new destination chain CCIP Collector contract
    /// @param _chainId the chain selector
    /// @param _collectorAddress Chainlink predefined selector per chain
    function setCollectorForChain(
        uint64 _chainId,
        address _collectorAddress,
        uint _slot
    ) external onlyOwner {
        require(masterCollector == address(this) && localChainSelector == masterCollectorChain, "NonMasterCollector");
        require(_slot <= numOfActiveCollectors, "SlotTooBig");
        if (_slot == numOfActiveCollectors) {
            chainSelector[numOfActiveCollectors] = _chainId;
            collectorAddress[_chainId] = _collectorAddress;
            chainSelectorIndex[_chainId] = numOfActiveCollectors;
            ++numOfActiveCollectors;
        } else if (collectorAddress[_chainId] == address(0) && _collectorAddress == address(0)) {
            --numOfActiveCollectors;
            (collectorAddress[_chainId], chainSelector[chainSelectorIndex[_chainId]]) = (
                collectorAddress[chainSelector[numOfActiveCollectors]],
                chainSelector[numOfActiveCollectors]
            );
            delete collectorAddress[chainSelector[numOfActiveCollectors]];
            delete chainSelector[numOfActiveCollectors];
        } else {
            chainSelector[_slot] = _chainId;
            collectorAddress[_chainId] = _collectorAddress;
            chainSelectorIndex[_chainId] = _slot;
        }
        emit CollectorForChainSet(_chainId, _collectorAddress);
    }

    /// @notice Reset most of the data in the contract
    function resetAllData() external onlyOwner {
        require(numOfActiveCollectors > 0, "AlreadyResetAllSlots");
        for (uint i = 0; i < numOfActiveCollectors; i++) {
            delete chainSelectorIndex[chainSelector[i]];
            delete collectorAddress[chainSelector[i]];
            delete chainSelector[i];
            lastPeriodForChain[chainSelector[i]] = 0;
        }
        numOfActiveCollectors = 0;
        collectedResultsForPeriod = 0;
        masterCollector = address(0);
        masterCollectorChain = 0;
        period = 0;
        numOfMessagesReceived = 0;
        baseRewardsPerPeriod = 0;
        extraRewardsPerPeriod = 0;
        emit RemovedAllData();
    }

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

    // Event emitted when a message is sent to another chain.
    event MessageSent(
        bytes32 indexed messageId, // The unique ID of the CCIP message.
        uint64 indexed destinationChainSelector, // The chain selector of the destination chain.
        address receiver, // The address of the receiver on the destination chain.
        bytes text, // The text being sent.
        address feeToken, // the token address used to pay CCIP fees.
        uint256 fees // The fees paid for sending the CCIP message.
    );

    // Event emitted when a message is received from another chain.
    event MessageReceived(
        bytes32 indexed messageId, // The unique ID of the message.
        uint64 indexed sourceChainSelector, // The chain selector of the source chain.
        address sender, // The address of the sender from the source chain.
        bytes data // The text that was received.
    );

    event CollectorForChainSet(uint64 chainId, address collectorAddress);
    event MasterCollectorSet(address masterCollector, uint64 materCollectorChainId);
    event SetPeriodRewards(uint _baseRewardsPerPeriod, uint _extraRewardsPerPeriod, uint _weeklyDecreaseFactor);
    event SetCCIPRouter(address _router);
    event SetAddressManager(address _addressManager);
    event SentOnClosePeriod(
        uint _totalStakedLastPeriodEnd,
        uint _totalEscrowedLastPeriodEnd,
        uint _bonusPoints,
        uint _revShare
    );
    event SetGasLimit(uint _gasLimitUsed);
    event RemovedAllData();
}

File 2 of 13 : IRouterClient.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {Client} from "../libraries/Client.sol";

interface IRouterClient {
  error UnsupportedDestinationChain(uint64 destChainSelector);
  error InsufficientFeeTokenAmount();
  error InvalidMsgValue();

  /// @notice Checks if the given chain ID is supported for sending/receiving.
  /// @param chainSelector The chain to check.
  /// @return supported is true if it is supported, false if not.
  function isChainSupported(uint64 chainSelector) external view returns (bool supported);

  /// @notice Gets a list of all supported tokens which can be sent or received
  /// to/from a given chain id.
  /// @param chainSelector The chainSelector.
  /// @return tokens The addresses of all tokens that are supported.
  function getSupportedTokens(uint64 chainSelector) external view returns (address[] memory tokens);

  /// @param destinationChainSelector The destination chainSelector
  /// @param message The cross-chain CCIP message including data and/or tokens
  /// @return fee returns guaranteed execution fee for the specified message
  /// delivery to destination chain
  /// @dev returns 0 fee on invalid message.
  function getFee(
    uint64 destinationChainSelector,
    Client.EVM2AnyMessage memory message
  ) external view returns (uint256 fee);

  /// @notice Request a message to be sent to the destination chain
  /// @param destinationChainSelector The destination chain ID
  /// @param message The cross-chain CCIP message including data and/or tokens
  /// @return messageId The message ID
  /// @dev Note if msg.value is larger than the required fee (from getFee) we accept
  /// the overpayment with no refund.
  function ccipSend(
    uint64 destinationChainSelector,
    Client.EVM2AnyMessage calldata message
  ) external payable returns (bytes32);
}

File 3 of 13 : Client.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// End consumer library.
library Client {
  struct EVMTokenAmount {
    address token; // token address on the local chain.
    uint256 amount; // Amount of tokens.
  }

  struct Any2EVMMessage {
    bytes32 messageId; // MessageId corresponding to ccipSend on source.
    uint64 sourceChainSelector; // Source chain selector.
    bytes sender; // abi.decode(sender) if coming from an EVM chain.
    bytes data; // payload sent in original message.
    EVMTokenAmount[] destTokenAmounts; // Tokens and their amounts in their destination chain representation.
  }

  // If extraArgs is empty bytes, the default is 200k gas limit and strict = false.
  struct EVM2AnyMessage {
    bytes receiver; // abi.encode(receiver address) for dest EVM chains
    bytes data; // Data payload
    EVMTokenAmount[] tokenAmounts; // Token transfers
    address feeToken; // Address of feeToken. address(0) means you will send msg.value.
    bytes extraArgs; // Populate this with _argsToBytes(EVMExtraArgsV1)
  }

  // extraArgs will evolve to support new features
  // bytes4(keccak256("CCIP EVMExtraArgsV1"));
  bytes4 public constant EVM_EXTRA_ARGS_V1_TAG = 0x97a657c9;
  struct EVMExtraArgsV1 {
    uint256 gasLimit; // ATTENTION!!! MAX GAS LIMIT 4M FOR BETA TESTING
    bool strict; // See strict sequencing details below.
  }

  function _argsToBytes(EVMExtraArgsV1 memory extraArgs) internal pure returns (bytes memory bts) {
    return abi.encodeWithSelector(EVM_EXTRA_ARGS_V1_TAG, extraArgs);
  }
}

File 4 of 13 : Initializable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/utils/Initializable.sol)

pragma solidity ^0.8.0;

import "../../utils/AddressUpgradeable.sol";

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the
 * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() initializer {}
 * ```
 * ====
 */
abstract 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 protect an initializer function from being invoked twice.
     */
    modifier initializer() {
        // If the contract is initializing we ignore whether _initialized is set in order to support multiple
        // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the
        // contract may have been reentered.
        require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized");

        bool isTopLevelCall = !_initializing;
        if (isTopLevelCall) {
            _initializing = true;
            _initialized = true;
        }

        _;

        if (isTopLevelCall) {
            _initializing = false;
        }
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} modifier, directly or indirectly.
     */
    modifier onlyInitializing() {
        require(_initializing, "Initializable: contract is not initializing");
        _;
    }

    function _isConstructor() private view returns (bool) {
        return !AddressUpgradeable.isContract(address(this));
    }
}

File 5 of 13 : ProxyReentrancyGuard.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the `nonReentrant` modifier
 * available, which can be 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 6 of 13 : ProxyOwned.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

// 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 7 of 13 : ProxyPausable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

// 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 8 of 13 : 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 9 of 13 : IAddressManager.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.5.16;

interface IAddressManager {
    struct Addresses {
        address safeBox;
        address referrals;
        address stakingThales;
        address multiCollateralOnOffRamp;
        address pyth;
        address speedMarketsAMM;
    }

    function safeBox() external view returns (address);

    function referrals() external view returns (address);

    function stakingThales() external view returns (address);

    function multiCollateralOnOffRamp() external view returns (address);

    function pyth() external view returns (address);

    function speedMarketsAMM() external view returns (address);

    function getAddresses() external view returns (Addresses memory);

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

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

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

File 10 of 13 : CCIPReceiverProxy.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IAny2EVMMessageReceiver} from "@chainlink/contracts-ccip/src/v0.8/ccip/interfaces/IAny2EVMMessageReceiver.sol";

import {Client} from "@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Client.sol";

import {IERC165} from "@chainlink/contracts-ccip/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/utils/introspection/IERC165.sol";

/// @title - Cross Chain Collector contract for Thales staking rewards
abstract contract CCIPReceiverProxy is IAny2EVMMessageReceiver, IERC165 {
    address internal i_router;

    function _setRouter(address router) internal {
        if (router == address(0)) revert InvalidRouter(address(0));
        i_router = router;
    }

    /// @notice IERC165 supports an interfaceId
    /// @param interfaceId The interfaceId to check
    /// @return true if the interfaceId is supported
    function supportsInterface(bytes4 interfaceId) public pure override returns (bool) {
        return interfaceId == type(IAny2EVMMessageReceiver).interfaceId || interfaceId == type(IERC165).interfaceId;
    }

    /// @inheritdoc IAny2EVMMessageReceiver
    function ccipReceive(Client.Any2EVMMessage calldata message) external virtual override onlyRouter {
        _ccipReceive(message);
    }

    /// @notice Override this function in your implementation.
    /// @param message Any2EVMMessage
    function _ccipReceive(Client.Any2EVMMessage memory message) internal virtual;

    /// @notice Return the current router
    /// @return i_router address
    function getRouter() public view returns (address) {
        return address(i_router);
    }

    error InvalidRouter(address router);

    /// @dev only calls from the set router are accepted.
    modifier onlyRouter() {
        if (msg.sender != address(i_router)) revert InvalidRouter(msg.sender);
        _;
    }
}

File 11 of 13 : AddressUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Address.sol)

pragma solidity ^0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library AddressUpgradeable {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 12 of 13 : IAny2EVMMessageReceiver.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {Client} from "../libraries/Client.sol";

/// @notice Application contracts that intend to receive messages from
/// the router should implement this interface.
interface IAny2EVMMessageReceiver {
  /// @notice Called by the Router to deliver a message.
  /// If this reverts, any token transfers also revert. The message
  /// will move to a FAILED state and become available for manual execution.
  /// @param message CCIP Message
  /// @dev Note ensure you check the msg.sender is the OffRampRouter
  function ccipReceive(Client.Any2EVMMessage calldata message) external;
}

File 13 of 13 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
  /**
    * @dev Returns true if this contract implements the interface defined by
    * `interfaceId`. See the corresponding
    * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
    * to learn more about how these ids are created.
    *
    * This function call must use less than 30 000 gas.
    */
  function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"router","type":"address"}],"name":"InvalidRouter","type":"error"},{"inputs":[{"internalType":"uint256","name":"currentBalance","type":"uint256"},{"internalType":"uint256","name":"calculatedFees","type":"uint256"}],"name":"NotEnoughBalance","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"chainId","type":"uint64"},{"indexed":false,"internalType":"address","name":"collectorAddress","type":"address"}],"name":"CollectorForChainSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"masterCollector","type":"address"},{"indexed":false,"internalType":"uint64","name":"materCollectorChainId","type":"uint64"}],"name":"MasterCollectorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"messageId","type":"bytes32"},{"indexed":true,"internalType":"uint64","name":"sourceChainSelector","type":"uint64"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"MessageReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"messageId","type":"bytes32"},{"indexed":true,"internalType":"uint64","name":"destinationChainSelector","type":"uint64"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"bytes","name":"text","type":"bytes"},{"indexed":false,"internalType":"address","name":"feeToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"fees","type":"uint256"}],"name":"MessageSent","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":[],"name":"RemovedAllData","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_totalStakedLastPeriodEnd","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_totalEscrowedLastPeriodEnd","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_bonusPoints","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_revShare","type":"uint256"}],"name":"SentOnClosePeriod","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_addressManager","type":"address"}],"name":"SetAddressManager","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_router","type":"address"}],"name":"SetCCIPRouter","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_gasLimitUsed","type":"uint256"}],"name":"SetGasLimit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_baseRewardsPerPeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_extraRewardsPerPeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_weeklyDecreaseFactor","type":"uint256"}],"name":"SetPeriodRewards","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"baseRewardsPerPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"broadcastMessageToAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"calculatedBonusPointsForPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"calculatedEscrowedAmountForPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"calculatedRevenueForPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"calculatedStakedAmountForPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"messageId","type":"bytes32"},{"internalType":"uint64","name":"sourceChainSelector","type":"uint64"},{"internalType":"bytes","name":"sender","type":"bytes"},{"internalType":"bytes","name":"data","type":"bytes"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct Client.EVMTokenAmount[]","name":"destTokenAmounts","type":"tuple[]"}],"internalType":"struct Client.Any2EVMMessage","name":"message","type":"tuple"}],"name":"ccipReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"chainBaseRewardsInPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"chainBonusPointsInPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"chainEscrowedAmountInPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"chainExtraRewardsInPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"chainRevenueInPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"chainRevenueShareInPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"chainSelector","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"","type":"uint64"}],"name":"chainSelectorIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"chainStakedAmountInPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collectedResultsForPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"collectorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"extraRewardsPerPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gasLimitUsed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getChainSelectorForLastMessage","outputs":[{"internalType":"uint64","name":"chainSelector_","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRouter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initNonReentrant","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_router","type":"address"},{"internalType":"bool","name":"_masterCollector","type":"bool"},{"internalType":"uint64","name":"_masterCollectorSelector","type":"uint64"},{"internalType":"uint64","name":"_localChainSelector","type":"uint64"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isMasterCollector","outputs":[{"internalType":"bool","name":"isMaster","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastPauseTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"lastPeriodForChain","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"localChainSelector","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"masterCollector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"masterCollectorChain","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"messageIdAlreadyReceived","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"messagesReceived","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"messagesReceivedFromChainSelector","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"nominateNewOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numOfActiveCollectors","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numOfMessagesReceived","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"period","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"readyToBroadcast","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"resetAllData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_totalStakedLastPeriodEnd","type":"uint256"},{"internalType":"uint256","name":"_totalEscrowedLastPeriodEnd","type":"uint256"},{"internalType":"uint256","name":"_bonusPoints","type":"uint256"},{"internalType":"uint256","name":"_revShare","type":"uint256"}],"name":"sendOnClosePeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_totalStakedLastPeriodEnd","type":"uint256"},{"internalType":"uint256","name":"_totalEscrowedLastPeriodEnd","type":"uint256"},{"internalType":"uint256","name":"_bonusPoints","type":"uint256"},{"internalType":"uint256","name":"_revShare","type":"uint256"}],"name":"sendOnClosePeriodAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_addressManager","type":"address"}],"name":"setAddressManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_router","type":"address"}],"name":"setCCIPRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_chainId","type":"uint64"},{"internalType":"address","name":"_collectorAddress","type":"address"},{"internalType":"uint256","name":"_slot","type":"uint256"}],"name":"setCollectorForChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_gasLimitUsed","type":"uint256"}],"name":"setGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_masterCollector","type":"address"},{"internalType":"uint64","name":"_materCollectorChainId","type":"uint64"},{"internalType":"uint64","name":"_localChainSelector","type":"uint64"}],"name":"setMasterCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_paused","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_baseRewardsPerPeriod","type":"uint256"},{"internalType":"uint256","name":"_extraRewardsPerPeriod","type":"uint256"},{"internalType":"uint256","name":"_weeklyDecreaseFactor","type":"uint256"}],"name":"setPeriodRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"proxyAddress","type":"address"}],"name":"transferOwnershipAtInit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"weeklyRewardsDecreaseFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

608060405234801561001057600080fd5b50613168806100206000396000f3fe60806040526004361061036d5760003560e01c8063735744e9116101c6578063b0f479a1116100f7578063e74ca38d11610095578063ee7d72b41161006f578063ee7d72b414610b1a578063ef5aea6b14610b3a578063ef78d4fd14610b4f578063fa31ce7c14610b6557600080fd5b8063e74ca38d14610ac4578063ebc7977214610aeb578063edb5eef114610b0057600080fd5b8063d874de60116100d1578063d874de6014610a08578063dadcea4d14610a40578063e083db7e14610a56578063e36fa14114610a8e57600080fd5b8063b0f479a1146109a5578063bd2521d2146109c8578063c3b83f5f146109e857600080fd5b80638da5cb5b11610164578063940c1f491161013e578063940c1f49146108ff57806399f1cfd4146109375780639c3971ce14610957578063a00301eb1461096d57600080fd5b80638da5cb5b146108935780638f32a302146108b957806391b4ded9146108e957600080fd5b806385572ffb116101a057806385572ffb146107e157806386c4f4d7146108015780638b3c0e351461082e5780638b9780621461085b57600080fd5b8063735744e91461076757806379ba50971461079f57806379f54976146107b457600080fd5b80633424c3bb116102a05780635614fe8f1161023e5780635d0e31fb116102185780635d0e31fb146106e557806366eb91361461070557806370c6abf514610725578063710183891461073a57600080fd5b80635614fe8f146106755780635c6f4860146106ab5780635c975abb146106cb57600080fd5b8063441b8a761161027a578063441b8a76146106095780634e03185b1461062957806352df2f401461063f57806353a47bb71461065557600080fd5b80633424c3bb146105be57806334bd229c146105d35780633b6f3ec0146105f357600080fd5b806316c38b3c1161030d5780631ee3d3ec116102e75780631ee3d3ec146104fc5780632ca5214c1461053b57806331c1e16a14610550578063323a2bee1461057057600080fd5b806316c38b3c1461049957806318030599146104b95780631e45403a146104e657600080fd5b80630652b57a116103495780630652b57a1461040a5780630ae12fc81461042c57806313af4035146104595780631627540c1461047957600080fd5b806204398b1461037957806237f079146103a257806301ffc9a7146103da57600080fd5b3661037457005b600080fd5b34801561038557600080fd5b5061038f601e5481565b6040519081526020015b60405180910390f35b3480156103ae57600080fd5b5061038f6103bd366004612c27565b600d60209081526000928352604080842090915290825290205481565b3480156103e657600080fd5b506103fa6103f5366004612bc8565b610b92565b6040519015158152602001610399565b34801561041657600080fd5b5061042a610425366004612aa6565b610bc9565b005b34801561043857600080fd5b5061038f610447366004612d06565b600a6020526000908152604090205481565b34801561046557600080fd5b5061042a610474366004612aa6565b610c26565b34801561048557600080fd5b5061042a610494366004612aa6565b610d5f565b3480156104a557600080fd5b5061042a6104b4366004612b7e565b610db5565b3480156104c557600080fd5b506104d96104d4366004612b98565b610e2b565b6040516103999190612e09565b3480156104f257600080fd5b5061038f601b5481565b34801561050857600080fd5b5060085461052390600160a01b90046001600160401b031681565b6040516001600160401b039091168152602001610399565b34801561054757600080fd5b5061042a610ec5565b34801561055c57600080fd5b5061042a61056b366004612aa6565b610fd1565b34801561057c57600080fd5b506105a661058b366004612b98565b600b602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610399565b3480156105ca57600080fd5b50610523611030565b3480156105df57600080fd5b5061042a6105ee366004612ca0565b61106e565b3480156105ff57600080fd5b5061038f601c5481565b34801561061557600080fd5b5061042a610624366004612ca0565b611161565b34801561063557600080fd5b5061038f60245481565b34801561064b57600080fd5b5061038f60205481565b34801561066157600080fd5b506001546105a6906001600160a01b031681565b34801561068157600080fd5b50610523610690366004612b98565b6019602052600090815260409020546001600160401b031681565b3480156106b757600080fd5b5061042a6106c6366004612ae5565b61117b565b3480156106d757600080fd5b506003546103fa9060ff1681565b3480156106f157600080fd5b5061042a610700366004612d20565b61133f565b34801561071157600080fd5b506008546105a6906001600160a01b031681565b34801561073157600080fd5b5061042a611616565b34801561074657600080fd5b5061038f610755366004612b98565b600c6020526000908152604090205481565b34801561077357600080fd5b5061038f610782366004612c27565b601060209081526000928352604080842090915290825290205481565b3480156107ab57600080fd5b5061042a61175c565b3480156107c057600080fd5b5061038f6107cf366004612b98565b60176020526000908152604090205481565b3480156107ed57600080fd5b5061042a6107fc366004612bf0565b611859565b34801561080d57600080fd5b5061038f61081c366004612b98565b60156020526000908152604090205481565b34801561083a57600080fd5b5061038f610849366004612b98565b60166020526000908152604090205481565b34801561086757600080fd5b5061038f610876366004612c27565b600f60209081526000928352604080842090915290825290205481565b34801561089f57600080fd5b506000546105a6906201000090046001600160a01b031681565b3480156108c557600080fd5b506103fa6108d4366004612b98565b60186020526000908152604090205460ff1681565b3480156108f557600080fd5b5061038f60025481565b34801561090b57600080fd5b5061038f61091a366004612c27565b600e60209081526000928352604080842090915290825290205481565b34801561094357600080fd5b5061042a610952366004612b3a565b61189c565b34801561096357600080fd5b5061038f601f5481565b34801561097957600080fd5b5061038f610988366004612c27565b601160209081526000928352604080842090915290825290205481565b3480156109b157600080fd5b5060055461010090046001600160a01b03166105a6565b3480156109d457600080fd5b5061042a6109e3366004612c48565b6119b3565b3480156109f457600080fd5b5061042a610a03366004612aa6565b611a08565b348015610a1457600080fd5b5061038f610a23366004612c27565b601360209081526000928352604080842090915290825290205481565b348015610a4c57600080fd5b5061038f60235481565b348015610a6257600080fd5b5061038f610a71366004612c27565b601260209081526000928352604080842090915290825290205481565b348015610a9a57600080fd5b50610523610aa9366004612b98565b6009602052600090815260409020546001600160401b031681565b348015610ad057600080fd5b5060255461052390600160a01b90046001600160401b031681565b348015610af757600080fd5b5061042a611b21565b348015610b0c57600080fd5b506022546103fa9060ff1681565b348015610b2657600080fd5b5061042a610b35366004612b98565b611b7f565b348015610b4657600080fd5b506103fa611c0b565b348015610b5b57600080fd5b5061038f601d5481565b348015610b7157600080fd5b5061038f610b80366004612b98565b60146020526000908152604090205481565b60006001600160e01b031982166385572ffb60e01b1480610bc357506001600160e01b031982166301ffc9a760e01b145b92915050565b610bd1611c49565b602580546001600160a01b0319166001600160a01b0383169081179091556040519081527f954328d28753080b3c499697bde218fd8b53e924669801835383aa346e6940ee906020015b60405180910390a150565b6001600160a01b038116610c815760405162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f7420626520300000000000000060448201526064015b60405180910390fd5b600154600160a01b900460ff1615610ced5760405162461bcd60e51b815260206004820152602960248201527f416c726561647920696e697469616c697a65642c20757365206e6f6d696e617460448201526832a732bba7bbb732b960b91b6064820152608401610c78565b6001805460ff60a01b1916600160a01b179055600080546001600160a01b03831662010000810262010000600160b01b03199092169190911782556040805192835260208301919091527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9101610c1b565b610d67611c49565b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290602001610c1b565b610dbd611c49565b60035460ff1615158115151415610dd15750565b6003805460ff191682151590811790915560ff1615610def57426002555b60035460405160ff909116151581527f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec590602001610c1b565b50565b601a6020526000908152604090208054610e449061309b565b80601f0160208091040260200160405190810160405280929190818152602001828054610e709061309b565b8015610ebd5780601f10610e9257610100808354040283529160200191610ebd565b820191906000526020600020905b815481529060010190602001808311610ea057829003601f168201915b505050505081565b600160046000828254610ed89190612f6e565b909155505060045460225460ff1680610f0157506000546201000090046001600160a01b031633145b610f435760405162461bcd60e51b8152602060048201526013602482015272139bdd149958591e551bd09c9bd85918d85cdd606a1b6044820152606401610c78565b610f4b611cc3565b600060208190556022805460ff19169055601d8054909190610f6c906130d6565b9091555060245415610f8057610f80611f0d565b6004548114610e285760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c78565b610fd9611c49565b610fe281611f5b565b600680546001600160a01b0319166001600160a01b0383169081179091556040519081527f28dfffa003cbac2f767191365506e49c4aba7ab310ebfa0a9d770e90f1b4550e90602001610c1b565b601b546000901561106b57601960006001601b5461104e9190612fc5565b81526020810191909152604001600020546001600160401b031690505b90565b60255460405163bf40fac160e01b815260206004820152600d60248201526c5374616b696e675468616c657360981b60448201526000916001600160a01b03169063bf40fac19060640160206040518083038186803b1580156110d057600080fd5b505afa1580156110e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111089190612ac9565b9050336001600160a01b0382161461114e5760405162461bcd60e51b815260206004820152600960248201526824b73b29b2b73232b960b91b6044820152606401610c78565b61115a85858585611fad565b5050505050565b611169611c49565b61117584848484611fad565b50505050565b600054610100900460ff166111965760005460ff161561119a565b303b155b6111fd5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610c78565b600054610100900460ff1615801561121f576000805461ffff19166101011790555b61122833610c26565b611230611b21565b61123985611f5b565b600680546001600160a01b0319166001600160a01b038716179055620f42406023556025805467ffffffffffffffff60a01b1916600160a01b6001600160401b03851602179055831561132757600880546001600160401b038516600160a01b810267ffffffffffffffff60a01b19309081166001600160e01b031990941693909317179092557fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b805467ffffffffffffffff1916831790556000918252600b6020908152604080842080546001600160a01b031916909317909255600a90528120556001601c819055601d555b801561115a576000805461ff00191690555050505050565b611347611c49565b6008546001600160a01b03163014801561137d5750600854602554600160a01b918290046001600160401b039081169290910416145b6113be5760405162461bcd60e51b81526020600482015260126024820152712737b726b0b9ba32b921b7b63632b1ba37b960711b6044820152606401610c78565b601c548111156113fd5760405162461bcd60e51b815260206004820152600a602482015269536c6f74546f6f42696760b01b6044820152606401610c78565b601c5481141561147957601c80546000908152600960209081526040808320805467ffffffffffffffff19166001600160401b0389169081179091558352600b825280832080546001600160a01b0319166001600160a01b0388161790558354600a9092528220819055611470906130d6565b909155506115c6565b6001600160401b0383166000908152600b60205260409020546001600160a01b03161580156114af57506001600160a01b038216155b1561156b57601c600081546114c390613084565b90915550601c80546000908152600960208181526040808420546001600160401b03908116808652600b808552838720548b84168852848820600a8752858920548952878752858920805467ffffffffffffffff19908116909517905580546001600160a01b039092166001600160a01b03199283161790558854885284882054909316875284528286208054909216909155945484529190529020805490911690556115c6565b6000818152600960209081526040808320805467ffffffffffffffff19166001600160401b0388169081179091558352600b825280832080546001600160a01b0319166001600160a01b038716179055600a90915290208190555b604080516001600160401b03851681526001600160a01b03841660208201527fd0983e2eb7b3d3254287f511871438d35f972763744ee70fb7602c9138e87db591015b60405180910390a1505050565b61161e611c49565b6000601c54116116675760405162461bcd60e51b8152602060048201526014602482015273416c72656164795265736574416c6c536c6f747360601b6044820152606401610c78565b60005b601c5481101561170257600081815260096020908152604080832080546001600160401b039081168552600a84528285208590558154168452600b835290832080546001600160a01b0319169055805467ffffffffffffffff19169055818052600c90527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e855806116fa816130d6565b91505061166a565b506000601c8190556020819055600880546001600160e01b0319169055601d819055601b819055601e819055601f8190556040517f644dd06f87fb842a04214a40a697e4132072aa972f69ae0160ac00af6580f0ca9190a1565b6001546001600160a01b031633146117d45760405162461bcd60e51b815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527402063616e20616363657074206f776e65727368697605c1b6064820152608401610c78565b60005460015460408051620100009093046001600160a01b03908116845290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a1600180546000805462010000600160b01b0319166001600160a01b03831662010000021790556001600160a01b0319169055565b60055461010090046001600160a01b0316331461188b576040516335fdcccd60e21b8152336004820152602401610c78565b610e2861189782612fdc565b61212a565b6118a4611c49565b6025805467ffffffffffffffff60a01b1916600160a01b6001600160401b03848116820292909217909255600880546001600160a01b0387166001600160e01b031990911681179286169384029290921790556000828152600b6020908152604080832080546001600160a01b0319169094179093557fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b805467ffffffffffffffff1916909417909355600a909252812055601c541561196657601c54611969565b60015b601c55604080516001600160a01b03851681526001600160401b03841660208201527fdd3bc5fc3811d69c4fec34eef96db67bf7f4531c4ee58a2ccbe73dff6d101fa49101611609565b6119bb611c49565b601e839055601f829055602481905560408051848152602081018490529081018290527f8f7cf43f4249e03d87a0085c85dd26618fac740b3f19740aace8f3737f43e10090606001611609565b611a10611c49565b6001600160a01b038116611a585760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b6044820152606401610c78565b600154600160a81b900460ff1615611aa85760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481d1c985b9cd9995c9c9959606a1b6044820152606401610c78565b600080546001600160a01b038381166201000081810262010000600160b01b031990941693909317938490556001805460ff60a81b1916600160a81b1790556040805193909404909116825260208201527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9101610c1b565b60055460ff1615611b6a5760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b6044820152606401610c78565b6005805460ff19166001908117909155600455565b611b87611c49565b611b95620f4240600a612fa6565b811115611bd65760405162461bcd60e51b815260206004820152600f60248201526e45786365656473204d41585f47415360881b6044820152606401610c78565b60238190556040518181527ff5bdeca176beddded5a1132996e4edf0d16be5100214b17d8bada54bf867629790602001610c1b565b6008546000906001600160a01b031630148015611c445750600854602554600160a01b918290046001600160401b039081169290910416145b905090565b6000546201000090046001600160a01b03163314611cc15760405162461bcd60e51b815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201526e37b936903a3434b99030b1ba34b7b760891b6064820152608401610c78565b565b6000806000606060005b601c5481101561115a57600081815260096020908152604080832054601d548452601583528184205460149093529220546001600160401b0390921691611d149190612f6e565b601e54601d546000818152600e602090815260408083206001600160401b03881680855290835281842054948452600d8352818420908452909152902054611d5c9190612f6e565b611d669190612fa6565b611d709190612f86565b601d54600090815260166020908152604080832054601f54601184528285206001600160401b03881686529093529220549298509091611db09190612fa6565b611dba9190612f86565b601d54600090815260156020908152604080832054601490925290912054919650611de491612f6e565b601d54600081815260176020908152604080832054600e83528184206001600160401b03881680865290845282852054958552600d8452828520908552909252909120549091611e3391612f6e565b611e3d9190612fa6565b611e479190612f86565b601d80546000908152600f602090815260408083206001600160401b038781168086529184528285208d9055855485526010845282852082865284528285208c9055945484526013835281842081855283529281902085905580519182018b90528181018a9052606080830186905281518084039091018152608090920190526008549397509550600160a01b909204161415611eee57611ee98686866123c2565b611efa565b611ef881846124cd565b505b5080611f05816130d6565b915050611ccd565b670de0b6b3a7640000602454601e54611f269190612fa6565b611f309190612f86565b601e55602454601f54670de0b6b3a764000091611f4c91612fa6565b611f569190612f86565b601f55565b6001600160a01b038116611f85576040516335fdcccd60e21b815260006004820152602401610c78565b600580546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6008546001600160a01b031630148015611fe35750600854602554600160a01b918290046001600160401b039081169290910416145b1561208a5760085461200890600160a01b90046001600160401b03168585858561276d565b601d54602554600160a01b90046001600160401b03166000908152600c6020526040902054101561206057602060008154612042906130d6565b90915550601c546020541415612060576022805460ff191660011790555b601d54602554600160a01b90046001600160401b03166000908152600c60205260409020556120dc565b60408051602081018690528082018590526060810184905260808082018490528251808303909101815260a09091019091526008546120d990600160a01b90046001600160401b0316826124cd565b50505b6040805185815260208101859052908101839052606081018290527f46aa3daf4ce91d0ef257a701581adf883b6da026f020849390f9f78a5f4292b59060800160405180910390a150505050565b805160009081526018602052604090205460ff1615801561215c5750602554600160a01b90046001600160401b031615155b15612358576000816040015180602001905181019061217b9190612ac9565b602083810151601b80546000908152601984526040808220805467ffffffffffffffff19166001600160401b0390951694909417909355606087015191548152601a84529190912081519394506121d893909291909101906128c9565b5081516000908152601860205260408120805460ff19166001179055601b8054909190612204906130d6565b909155506008546001600160a01b03163014801561223e5750600854602554600160a01b918290046001600160401b039081169290910416145b156122e4576020828101516001600160401b03166000818152600b9092526040909120546001600160a01b03838116911614801561228b5750601d546000828152600c6020526040902054105b156122de57601d546000828152600c602052604090205560608301516122b19082612868565b6020600081546122c0906130d6565b90915550601c5460205414156122de576022805460ff191660011790555b50612356565b6008546001600160a01b03828116911614801561231b57506020820151602554600160a01b90046001600160401b03908116911614155b80156123445750600854602554600160a01b918290046001600160401b03908116929091041614155b1561235657612356826060015161289f565b505b80602001516001600160401b031681600001517f4add8c8902d6fd412fed639bf652d936405bbb837c732a202153c91e89ebfaa783604001518060200190518101906123a49190612ac9565b84606001516040516123b7929190612da9565b60405180910390a350565b60255460405163bf40fac160e01b815260206004820152600d60248201526c5374616b696e675468616c657360981b60448201526000916001600160a01b03169063bf40fac19060640160206040518083038186803b15801561242457600080fd5b505afa158015612438573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061245c9190612ac9565b604051638759263f60e01b81526004810186905260248101859052604481018490529091506001600160a01b03821690638759263f90606401600060405180830381600087803b1580156124af57600080fd5b505af11580156124c3573d6000803e3d6000fd5b5050505050505050565b6040805160a0810182526001600160401b0384166000908152600b602052918220546001600160a01b031660c082015281908060e0810160408051808303601f19018152918152908252602080830187905281516000808252918101835292909101919061255d565b60408051808201909152600080825260208201528152602001906001900390816125365790505b508152600060208083018290526040805180820182526023548082529083019384528151602481019190915292511515604480850191909152815180850390910181526064909301815290820180516001600160e01b03166397a657c960e01b179052909101526006546040516320487ded60e01b81529192506000916001600160a01b03909116906320487ded906125fc9088908690600401612e1c565b60206040518083038186803b15801561261457600080fd5b505afa158015612628573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061264c9190612bb0565b90504781111561267857604051634787a10360e11b815247600482015260248101829052604401610c78565b6006546040516396f4e9f960e01b81526001600160a01b03909116906396f4e9f99083906126ac9089908790600401612e1c565b6020604051808303818588803b1580156126c557600080fd5b505af11580156126d9573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906126fe9190612bb0565b6001600160401b0386166000818152600b6020526040808220549051939650919286927f3d8a9f055772202d2c3c1fddbad930d3dbe588d8692b75b84cee0719462829119261275d926001600160a01b03909216918a91908890612dd5565b60405180910390a3505092915050565b601d80546000908152600d60209081526040808320898452825280832088905583548352600e825280832089845282528083208790558354835260118252808320898452825280832086905583548352601282528083208984528252808320859055925482526014905290812080548692906127ea908490612f6e565b9091555050601d5460009081526015602052604081208054859290612810908490612f6e565b9091555050601d5460009081526016602052604081208054849290612836908490612f6e565b9091555050601d546000908152601760205260408120805483929061285c908490612f6e565b90915550505050505050565b600080600080858060200190518101906128829190612cd1565b9350935093509350612897858585858561276d565b505050505050565b6000806000838060200190518101906128b89190612c73565b9250925092506111758383836123c2565b8280546128d59061309b565b90600052602060002090601f0160209004810192826128f7576000855561293d565b82601f1061291057805160ff191683800117855561293d565b8280016001018555821561293d579182015b8281111561293d578251825591602001919060010190612922565b5061294992915061294d565b5090565b5b80821115612949576000815560010161294e565b600082601f830112612972578081fd5b813560206001600160401b0382111561298d5761298d613107565b61299b818360051b01612f3e565b80838252828201915082860187848660061b89010111156129ba578586fd5b855b85811015612a0357604080838b0312156129d4578788fd5b6129dc612ef4565b83356129e78161311d565b81528387013587820152855293850193909101906001016129bc565b5090979650505050505050565b80358015158114612a2057600080fd5b919050565b600082601f830112612a35578081fd5b81356001600160401b03811115612a4e57612a4e613107565b612a61601f8201601f1916602001612f3e565b818152846020838601011115612a75578283fd5b816020850160208301379081016020019190915292915050565b80356001600160401b0381168114612a2057600080fd5b600060208284031215612ab7578081fd5b8135612ac28161311d565b9392505050565b600060208284031215612ada578081fd5b8151612ac28161311d565b60008060008060808587031215612afa578283fd5b8435612b058161311d565b9350612b1360208601612a10565b9250612b2160408601612a8f565b9150612b2f60608601612a8f565b905092959194509250565b600080600060608486031215612b4e578283fd5b8335612b598161311d565b9250612b6760208501612a8f565b9150612b7560408501612a8f565b90509250925092565b600060208284031215612b8f578081fd5b612ac282612a10565b600060208284031215612ba9578081fd5b5035919050565b600060208284031215612bc1578081fd5b5051919050565b600060208284031215612bd9578081fd5b81356001600160e01b031981168114612ac2578182fd5b600060208284031215612c01578081fd5b81356001600160401b03811115612c16578182fd5b820160a08185031215612ac2578182fd5b60008060408385031215612c39578182fd5b50508035926020909101359150565b600080600060608486031215612c5c578081fd5b505081359360208301359350604090920135919050565b600080600060608486031215612c87578081fd5b8351925060208401519150604084015190509250925092565b60008060008060808587031215612cb5578182fd5b5050823594602084013594506040840135936060013592509050565b60008060008060808587031215612ce6578182fd5b505082516020840151604085015160609095015191969095509092509050565b600060208284031215612d17578081fd5b612ac282612a8f565b600080600060608486031215612d34578081fd5b612d3d84612a8f565b92506020840135612d4d8161311d565b929592945050506040919091013590565b60008151808452815b81811015612d8357602081850181015186830182015201612d67565b81811115612d945782602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b0383168152604060208201819052600090612dcd90830184612d5e565b949350505050565b600060018060a01b03808716835260806020840152612df76080840187612d5e565b94166040830152506060015292915050565b602081526000612ac26020830184612d5e565b600060406001600160401b038516835260208181850152845160a083860152612e4860e0860182612d5e565b905081860151603f1980878403016060880152612e658383612d5e565b88860151888203830160808a015280518083529086019450879350908501905b80841015612eb757845180516001600160a01b0316835286015186830152938501936001939093019290860190612e85565b5060608901516001600160a01b031660a08901526080890151888203830160c08a01529550612ee68187612d5e565b9a9950505050505050505050565b604080519081016001600160401b0381118282101715612f1657612f16613107565b60405290565b60405160a081016001600160401b0381118282101715612f1657612f16613107565b604051601f8201601f191681016001600160401b0381118282101715612f6657612f66613107565b604052919050565b60008219821115612f8157612f816130f1565b500190565b600082612fa157634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615612fc057612fc06130f1565b500290565b600082821015612fd757612fd76130f1565b500390565b600060a08236031215612fed578081fd5b612ff5612f1c565b8235815261300560208401612a8f565b602082015260408301356001600160401b0380821115613023578384fd5b61302f36838701612a25565b60408401526060850135915080821115613047578384fd5b61305336838701612a25565b6060840152608085013591508082111561306b578384fd5b5061307836828601612962565b60808301525092915050565b600081613093576130936130f1565b506000190190565b600181811c908216806130af57607f821691505b602082108114156130d057634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156130ea576130ea6130f1565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610e2857600080fdfea2646970667358221220867d37c663daf1187a1d45eafdca5e37ecf389669ccacb83c3c1152d304a0def64736f6c63430008040033

Deployed Bytecode

0x60806040526004361061036d5760003560e01c8063735744e9116101c6578063b0f479a1116100f7578063e74ca38d11610095578063ee7d72b41161006f578063ee7d72b414610b1a578063ef5aea6b14610b3a578063ef78d4fd14610b4f578063fa31ce7c14610b6557600080fd5b8063e74ca38d14610ac4578063ebc7977214610aeb578063edb5eef114610b0057600080fd5b8063d874de60116100d1578063d874de6014610a08578063dadcea4d14610a40578063e083db7e14610a56578063e36fa14114610a8e57600080fd5b8063b0f479a1146109a5578063bd2521d2146109c8578063c3b83f5f146109e857600080fd5b80638da5cb5b11610164578063940c1f491161013e578063940c1f49146108ff57806399f1cfd4146109375780639c3971ce14610957578063a00301eb1461096d57600080fd5b80638da5cb5b146108935780638f32a302146108b957806391b4ded9146108e957600080fd5b806385572ffb116101a057806385572ffb146107e157806386c4f4d7146108015780638b3c0e351461082e5780638b9780621461085b57600080fd5b8063735744e91461076757806379ba50971461079f57806379f54976146107b457600080fd5b80633424c3bb116102a05780635614fe8f1161023e5780635d0e31fb116102185780635d0e31fb146106e557806366eb91361461070557806370c6abf514610725578063710183891461073a57600080fd5b80635614fe8f146106755780635c6f4860146106ab5780635c975abb146106cb57600080fd5b8063441b8a761161027a578063441b8a76146106095780634e03185b1461062957806352df2f401461063f57806353a47bb71461065557600080fd5b80633424c3bb146105be57806334bd229c146105d35780633b6f3ec0146105f357600080fd5b806316c38b3c1161030d5780631ee3d3ec116102e75780631ee3d3ec146104fc5780632ca5214c1461053b57806331c1e16a14610550578063323a2bee1461057057600080fd5b806316c38b3c1461049957806318030599146104b95780631e45403a146104e657600080fd5b80630652b57a116103495780630652b57a1461040a5780630ae12fc81461042c57806313af4035146104595780631627540c1461047957600080fd5b806204398b1461037957806237f079146103a257806301ffc9a7146103da57600080fd5b3661037457005b600080fd5b34801561038557600080fd5b5061038f601e5481565b6040519081526020015b60405180910390f35b3480156103ae57600080fd5b5061038f6103bd366004612c27565b600d60209081526000928352604080842090915290825290205481565b3480156103e657600080fd5b506103fa6103f5366004612bc8565b610b92565b6040519015158152602001610399565b34801561041657600080fd5b5061042a610425366004612aa6565b610bc9565b005b34801561043857600080fd5b5061038f610447366004612d06565b600a6020526000908152604090205481565b34801561046557600080fd5b5061042a610474366004612aa6565b610c26565b34801561048557600080fd5b5061042a610494366004612aa6565b610d5f565b3480156104a557600080fd5b5061042a6104b4366004612b7e565b610db5565b3480156104c557600080fd5b506104d96104d4366004612b98565b610e2b565b6040516103999190612e09565b3480156104f257600080fd5b5061038f601b5481565b34801561050857600080fd5b5060085461052390600160a01b90046001600160401b031681565b6040516001600160401b039091168152602001610399565b34801561054757600080fd5b5061042a610ec5565b34801561055c57600080fd5b5061042a61056b366004612aa6565b610fd1565b34801561057c57600080fd5b506105a661058b366004612b98565b600b602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610399565b3480156105ca57600080fd5b50610523611030565b3480156105df57600080fd5b5061042a6105ee366004612ca0565b61106e565b3480156105ff57600080fd5b5061038f601c5481565b34801561061557600080fd5b5061042a610624366004612ca0565b611161565b34801561063557600080fd5b5061038f60245481565b34801561064b57600080fd5b5061038f60205481565b34801561066157600080fd5b506001546105a6906001600160a01b031681565b34801561068157600080fd5b50610523610690366004612b98565b6019602052600090815260409020546001600160401b031681565b3480156106b757600080fd5b5061042a6106c6366004612ae5565b61117b565b3480156106d757600080fd5b506003546103fa9060ff1681565b3480156106f157600080fd5b5061042a610700366004612d20565b61133f565b34801561071157600080fd5b506008546105a6906001600160a01b031681565b34801561073157600080fd5b5061042a611616565b34801561074657600080fd5b5061038f610755366004612b98565b600c6020526000908152604090205481565b34801561077357600080fd5b5061038f610782366004612c27565b601060209081526000928352604080842090915290825290205481565b3480156107ab57600080fd5b5061042a61175c565b3480156107c057600080fd5b5061038f6107cf366004612b98565b60176020526000908152604090205481565b3480156107ed57600080fd5b5061042a6107fc366004612bf0565b611859565b34801561080d57600080fd5b5061038f61081c366004612b98565b60156020526000908152604090205481565b34801561083a57600080fd5b5061038f610849366004612b98565b60166020526000908152604090205481565b34801561086757600080fd5b5061038f610876366004612c27565b600f60209081526000928352604080842090915290825290205481565b34801561089f57600080fd5b506000546105a6906201000090046001600160a01b031681565b3480156108c557600080fd5b506103fa6108d4366004612b98565b60186020526000908152604090205460ff1681565b3480156108f557600080fd5b5061038f60025481565b34801561090b57600080fd5b5061038f61091a366004612c27565b600e60209081526000928352604080842090915290825290205481565b34801561094357600080fd5b5061042a610952366004612b3a565b61189c565b34801561096357600080fd5b5061038f601f5481565b34801561097957600080fd5b5061038f610988366004612c27565b601160209081526000928352604080842090915290825290205481565b3480156109b157600080fd5b5060055461010090046001600160a01b03166105a6565b3480156109d457600080fd5b5061042a6109e3366004612c48565b6119b3565b3480156109f457600080fd5b5061042a610a03366004612aa6565b611a08565b348015610a1457600080fd5b5061038f610a23366004612c27565b601360209081526000928352604080842090915290825290205481565b348015610a4c57600080fd5b5061038f60235481565b348015610a6257600080fd5b5061038f610a71366004612c27565b601260209081526000928352604080842090915290825290205481565b348015610a9a57600080fd5b50610523610aa9366004612b98565b6009602052600090815260409020546001600160401b031681565b348015610ad057600080fd5b5060255461052390600160a01b90046001600160401b031681565b348015610af757600080fd5b5061042a611b21565b348015610b0c57600080fd5b506022546103fa9060ff1681565b348015610b2657600080fd5b5061042a610b35366004612b98565b611b7f565b348015610b4657600080fd5b506103fa611c0b565b348015610b5b57600080fd5b5061038f601d5481565b348015610b7157600080fd5b5061038f610b80366004612b98565b60146020526000908152604090205481565b60006001600160e01b031982166385572ffb60e01b1480610bc357506001600160e01b031982166301ffc9a760e01b145b92915050565b610bd1611c49565b602580546001600160a01b0319166001600160a01b0383169081179091556040519081527f954328d28753080b3c499697bde218fd8b53e924669801835383aa346e6940ee906020015b60405180910390a150565b6001600160a01b038116610c815760405162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f7420626520300000000000000060448201526064015b60405180910390fd5b600154600160a01b900460ff1615610ced5760405162461bcd60e51b815260206004820152602960248201527f416c726561647920696e697469616c697a65642c20757365206e6f6d696e617460448201526832a732bba7bbb732b960b91b6064820152608401610c78565b6001805460ff60a01b1916600160a01b179055600080546001600160a01b03831662010000810262010000600160b01b03199092169190911782556040805192835260208301919091527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9101610c1b565b610d67611c49565b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290602001610c1b565b610dbd611c49565b60035460ff1615158115151415610dd15750565b6003805460ff191682151590811790915560ff1615610def57426002555b60035460405160ff909116151581527f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec590602001610c1b565b50565b601a6020526000908152604090208054610e449061309b565b80601f0160208091040260200160405190810160405280929190818152602001828054610e709061309b565b8015610ebd5780601f10610e9257610100808354040283529160200191610ebd565b820191906000526020600020905b815481529060010190602001808311610ea057829003601f168201915b505050505081565b600160046000828254610ed89190612f6e565b909155505060045460225460ff1680610f0157506000546201000090046001600160a01b031633145b610f435760405162461bcd60e51b8152602060048201526013602482015272139bdd149958591e551bd09c9bd85918d85cdd606a1b6044820152606401610c78565b610f4b611cc3565b600060208190556022805460ff19169055601d8054909190610f6c906130d6565b9091555060245415610f8057610f80611f0d565b6004548114610e285760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c78565b610fd9611c49565b610fe281611f5b565b600680546001600160a01b0319166001600160a01b0383169081179091556040519081527f28dfffa003cbac2f767191365506e49c4aba7ab310ebfa0a9d770e90f1b4550e90602001610c1b565b601b546000901561106b57601960006001601b5461104e9190612fc5565b81526020810191909152604001600020546001600160401b031690505b90565b60255460405163bf40fac160e01b815260206004820152600d60248201526c5374616b696e675468616c657360981b60448201526000916001600160a01b03169063bf40fac19060640160206040518083038186803b1580156110d057600080fd5b505afa1580156110e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111089190612ac9565b9050336001600160a01b0382161461114e5760405162461bcd60e51b815260206004820152600960248201526824b73b29b2b73232b960b91b6044820152606401610c78565b61115a85858585611fad565b5050505050565b611169611c49565b61117584848484611fad565b50505050565b600054610100900460ff166111965760005460ff161561119a565b303b155b6111fd5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610c78565b600054610100900460ff1615801561121f576000805461ffff19166101011790555b61122833610c26565b611230611b21565b61123985611f5b565b600680546001600160a01b0319166001600160a01b038716179055620f42406023556025805467ffffffffffffffff60a01b1916600160a01b6001600160401b03851602179055831561132757600880546001600160401b038516600160a01b810267ffffffffffffffff60a01b19309081166001600160e01b031990941693909317179092557fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b805467ffffffffffffffff1916831790556000918252600b6020908152604080842080546001600160a01b031916909317909255600a90528120556001601c819055601d555b801561115a576000805461ff00191690555050505050565b611347611c49565b6008546001600160a01b03163014801561137d5750600854602554600160a01b918290046001600160401b039081169290910416145b6113be5760405162461bcd60e51b81526020600482015260126024820152712737b726b0b9ba32b921b7b63632b1ba37b960711b6044820152606401610c78565b601c548111156113fd5760405162461bcd60e51b815260206004820152600a602482015269536c6f74546f6f42696760b01b6044820152606401610c78565b601c5481141561147957601c80546000908152600960209081526040808320805467ffffffffffffffff19166001600160401b0389169081179091558352600b825280832080546001600160a01b0319166001600160a01b0388161790558354600a9092528220819055611470906130d6565b909155506115c6565b6001600160401b0383166000908152600b60205260409020546001600160a01b03161580156114af57506001600160a01b038216155b1561156b57601c600081546114c390613084565b90915550601c80546000908152600960208181526040808420546001600160401b03908116808652600b808552838720548b84168852848820600a8752858920548952878752858920805467ffffffffffffffff19908116909517905580546001600160a01b039092166001600160a01b03199283161790558854885284882054909316875284528286208054909216909155945484529190529020805490911690556115c6565b6000818152600960209081526040808320805467ffffffffffffffff19166001600160401b0388169081179091558352600b825280832080546001600160a01b0319166001600160a01b038716179055600a90915290208190555b604080516001600160401b03851681526001600160a01b03841660208201527fd0983e2eb7b3d3254287f511871438d35f972763744ee70fb7602c9138e87db591015b60405180910390a1505050565b61161e611c49565b6000601c54116116675760405162461bcd60e51b8152602060048201526014602482015273416c72656164795265736574416c6c536c6f747360601b6044820152606401610c78565b60005b601c5481101561170257600081815260096020908152604080832080546001600160401b039081168552600a84528285208590558154168452600b835290832080546001600160a01b0319169055805467ffffffffffffffff19169055818052600c90527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e855806116fa816130d6565b91505061166a565b506000601c8190556020819055600880546001600160e01b0319169055601d819055601b819055601e819055601f8190556040517f644dd06f87fb842a04214a40a697e4132072aa972f69ae0160ac00af6580f0ca9190a1565b6001546001600160a01b031633146117d45760405162461bcd60e51b815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527402063616e20616363657074206f776e65727368697605c1b6064820152608401610c78565b60005460015460408051620100009093046001600160a01b03908116845290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a1600180546000805462010000600160b01b0319166001600160a01b03831662010000021790556001600160a01b0319169055565b60055461010090046001600160a01b0316331461188b576040516335fdcccd60e21b8152336004820152602401610c78565b610e2861189782612fdc565b61212a565b6118a4611c49565b6025805467ffffffffffffffff60a01b1916600160a01b6001600160401b03848116820292909217909255600880546001600160a01b0387166001600160e01b031990911681179286169384029290921790556000828152600b6020908152604080832080546001600160a01b0319169094179093557fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b805467ffffffffffffffff1916909417909355600a909252812055601c541561196657601c54611969565b60015b601c55604080516001600160a01b03851681526001600160401b03841660208201527fdd3bc5fc3811d69c4fec34eef96db67bf7f4531c4ee58a2ccbe73dff6d101fa49101611609565b6119bb611c49565b601e839055601f829055602481905560408051848152602081018490529081018290527f8f7cf43f4249e03d87a0085c85dd26618fac740b3f19740aace8f3737f43e10090606001611609565b611a10611c49565b6001600160a01b038116611a585760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b6044820152606401610c78565b600154600160a81b900460ff1615611aa85760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481d1c985b9cd9995c9c9959606a1b6044820152606401610c78565b600080546001600160a01b038381166201000081810262010000600160b01b031990941693909317938490556001805460ff60a81b1916600160a81b1790556040805193909404909116825260208201527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9101610c1b565b60055460ff1615611b6a5760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b6044820152606401610c78565b6005805460ff19166001908117909155600455565b611b87611c49565b611b95620f4240600a612fa6565b811115611bd65760405162461bcd60e51b815260206004820152600f60248201526e45786365656473204d41585f47415360881b6044820152606401610c78565b60238190556040518181527ff5bdeca176beddded5a1132996e4edf0d16be5100214b17d8bada54bf867629790602001610c1b565b6008546000906001600160a01b031630148015611c445750600854602554600160a01b918290046001600160401b039081169290910416145b905090565b6000546201000090046001600160a01b03163314611cc15760405162461bcd60e51b815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201526e37b936903a3434b99030b1ba34b7b760891b6064820152608401610c78565b565b6000806000606060005b601c5481101561115a57600081815260096020908152604080832054601d548452601583528184205460149093529220546001600160401b0390921691611d149190612f6e565b601e54601d546000818152600e602090815260408083206001600160401b03881680855290835281842054948452600d8352818420908452909152902054611d5c9190612f6e565b611d669190612fa6565b611d709190612f86565b601d54600090815260166020908152604080832054601f54601184528285206001600160401b03881686529093529220549298509091611db09190612fa6565b611dba9190612f86565b601d54600090815260156020908152604080832054601490925290912054919650611de491612f6e565b601d54600081815260176020908152604080832054600e83528184206001600160401b03881680865290845282852054958552600d8452828520908552909252909120549091611e3391612f6e565b611e3d9190612fa6565b611e479190612f86565b601d80546000908152600f602090815260408083206001600160401b038781168086529184528285208d9055855485526010845282852082865284528285208c9055945484526013835281842081855283529281902085905580519182018b90528181018a9052606080830186905281518084039091018152608090920190526008549397509550600160a01b909204161415611eee57611ee98686866123c2565b611efa565b611ef881846124cd565b505b5080611f05816130d6565b915050611ccd565b670de0b6b3a7640000602454601e54611f269190612fa6565b611f309190612f86565b601e55602454601f54670de0b6b3a764000091611f4c91612fa6565b611f569190612f86565b601f55565b6001600160a01b038116611f85576040516335fdcccd60e21b815260006004820152602401610c78565b600580546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6008546001600160a01b031630148015611fe35750600854602554600160a01b918290046001600160401b039081169290910416145b1561208a5760085461200890600160a01b90046001600160401b03168585858561276d565b601d54602554600160a01b90046001600160401b03166000908152600c6020526040902054101561206057602060008154612042906130d6565b90915550601c546020541415612060576022805460ff191660011790555b601d54602554600160a01b90046001600160401b03166000908152600c60205260409020556120dc565b60408051602081018690528082018590526060810184905260808082018490528251808303909101815260a09091019091526008546120d990600160a01b90046001600160401b0316826124cd565b50505b6040805185815260208101859052908101839052606081018290527f46aa3daf4ce91d0ef257a701581adf883b6da026f020849390f9f78a5f4292b59060800160405180910390a150505050565b805160009081526018602052604090205460ff1615801561215c5750602554600160a01b90046001600160401b031615155b15612358576000816040015180602001905181019061217b9190612ac9565b602083810151601b80546000908152601984526040808220805467ffffffffffffffff19166001600160401b0390951694909417909355606087015191548152601a84529190912081519394506121d893909291909101906128c9565b5081516000908152601860205260408120805460ff19166001179055601b8054909190612204906130d6565b909155506008546001600160a01b03163014801561223e5750600854602554600160a01b918290046001600160401b039081169290910416145b156122e4576020828101516001600160401b03166000818152600b9092526040909120546001600160a01b03838116911614801561228b5750601d546000828152600c6020526040902054105b156122de57601d546000828152600c602052604090205560608301516122b19082612868565b6020600081546122c0906130d6565b90915550601c5460205414156122de576022805460ff191660011790555b50612356565b6008546001600160a01b03828116911614801561231b57506020820151602554600160a01b90046001600160401b03908116911614155b80156123445750600854602554600160a01b918290046001600160401b03908116929091041614155b1561235657612356826060015161289f565b505b80602001516001600160401b031681600001517f4add8c8902d6fd412fed639bf652d936405bbb837c732a202153c91e89ebfaa783604001518060200190518101906123a49190612ac9565b84606001516040516123b7929190612da9565b60405180910390a350565b60255460405163bf40fac160e01b815260206004820152600d60248201526c5374616b696e675468616c657360981b60448201526000916001600160a01b03169063bf40fac19060640160206040518083038186803b15801561242457600080fd5b505afa158015612438573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061245c9190612ac9565b604051638759263f60e01b81526004810186905260248101859052604481018490529091506001600160a01b03821690638759263f90606401600060405180830381600087803b1580156124af57600080fd5b505af11580156124c3573d6000803e3d6000fd5b5050505050505050565b6040805160a0810182526001600160401b0384166000908152600b602052918220546001600160a01b031660c082015281908060e0810160408051808303601f19018152918152908252602080830187905281516000808252918101835292909101919061255d565b60408051808201909152600080825260208201528152602001906001900390816125365790505b508152600060208083018290526040805180820182526023548082529083019384528151602481019190915292511515604480850191909152815180850390910181526064909301815290820180516001600160e01b03166397a657c960e01b179052909101526006546040516320487ded60e01b81529192506000916001600160a01b03909116906320487ded906125fc9088908690600401612e1c565b60206040518083038186803b15801561261457600080fd5b505afa158015612628573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061264c9190612bb0565b90504781111561267857604051634787a10360e11b815247600482015260248101829052604401610c78565b6006546040516396f4e9f960e01b81526001600160a01b03909116906396f4e9f99083906126ac9089908790600401612e1c565b6020604051808303818588803b1580156126c557600080fd5b505af11580156126d9573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906126fe9190612bb0565b6001600160401b0386166000818152600b6020526040808220549051939650919286927f3d8a9f055772202d2c3c1fddbad930d3dbe588d8692b75b84cee0719462829119261275d926001600160a01b03909216918a91908890612dd5565b60405180910390a3505092915050565b601d80546000908152600d60209081526040808320898452825280832088905583548352600e825280832089845282528083208790558354835260118252808320898452825280832086905583548352601282528083208984528252808320859055925482526014905290812080548692906127ea908490612f6e565b9091555050601d5460009081526015602052604081208054859290612810908490612f6e565b9091555050601d5460009081526016602052604081208054849290612836908490612f6e565b9091555050601d546000908152601760205260408120805483929061285c908490612f6e565b90915550505050505050565b600080600080858060200190518101906128829190612cd1565b9350935093509350612897858585858561276d565b505050505050565b6000806000838060200190518101906128b89190612c73565b9250925092506111758383836123c2565b8280546128d59061309b565b90600052602060002090601f0160209004810192826128f7576000855561293d565b82601f1061291057805160ff191683800117855561293d565b8280016001018555821561293d579182015b8281111561293d578251825591602001919060010190612922565b5061294992915061294d565b5090565b5b80821115612949576000815560010161294e565b600082601f830112612972578081fd5b813560206001600160401b0382111561298d5761298d613107565b61299b818360051b01612f3e565b80838252828201915082860187848660061b89010111156129ba578586fd5b855b85811015612a0357604080838b0312156129d4578788fd5b6129dc612ef4565b83356129e78161311d565b81528387013587820152855293850193909101906001016129bc565b5090979650505050505050565b80358015158114612a2057600080fd5b919050565b600082601f830112612a35578081fd5b81356001600160401b03811115612a4e57612a4e613107565b612a61601f8201601f1916602001612f3e565b818152846020838601011115612a75578283fd5b816020850160208301379081016020019190915292915050565b80356001600160401b0381168114612a2057600080fd5b600060208284031215612ab7578081fd5b8135612ac28161311d565b9392505050565b600060208284031215612ada578081fd5b8151612ac28161311d565b60008060008060808587031215612afa578283fd5b8435612b058161311d565b9350612b1360208601612a10565b9250612b2160408601612a8f565b9150612b2f60608601612a8f565b905092959194509250565b600080600060608486031215612b4e578283fd5b8335612b598161311d565b9250612b6760208501612a8f565b9150612b7560408501612a8f565b90509250925092565b600060208284031215612b8f578081fd5b612ac282612a10565b600060208284031215612ba9578081fd5b5035919050565b600060208284031215612bc1578081fd5b5051919050565b600060208284031215612bd9578081fd5b81356001600160e01b031981168114612ac2578182fd5b600060208284031215612c01578081fd5b81356001600160401b03811115612c16578182fd5b820160a08185031215612ac2578182fd5b60008060408385031215612c39578182fd5b50508035926020909101359150565b600080600060608486031215612c5c578081fd5b505081359360208301359350604090920135919050565b600080600060608486031215612c87578081fd5b8351925060208401519150604084015190509250925092565b60008060008060808587031215612cb5578182fd5b5050823594602084013594506040840135936060013592509050565b60008060008060808587031215612ce6578182fd5b505082516020840151604085015160609095015191969095509092509050565b600060208284031215612d17578081fd5b612ac282612a8f565b600080600060608486031215612d34578081fd5b612d3d84612a8f565b92506020840135612d4d8161311d565b929592945050506040919091013590565b60008151808452815b81811015612d8357602081850181015186830182015201612d67565b81811115612d945782602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b0383168152604060208201819052600090612dcd90830184612d5e565b949350505050565b600060018060a01b03808716835260806020840152612df76080840187612d5e565b94166040830152506060015292915050565b602081526000612ac26020830184612d5e565b600060406001600160401b038516835260208181850152845160a083860152612e4860e0860182612d5e565b905081860151603f1980878403016060880152612e658383612d5e565b88860151888203830160808a015280518083529086019450879350908501905b80841015612eb757845180516001600160a01b0316835286015186830152938501936001939093019290860190612e85565b5060608901516001600160a01b031660a08901526080890151888203830160c08a01529550612ee68187612d5e565b9a9950505050505050505050565b604080519081016001600160401b0381118282101715612f1657612f16613107565b60405290565b60405160a081016001600160401b0381118282101715612f1657612f16613107565b604051601f8201601f191681016001600160401b0381118282101715612f6657612f66613107565b604052919050565b60008219821115612f8157612f816130f1565b500190565b600082612fa157634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615612fc057612fc06130f1565b500290565b600082821015612fd757612fd76130f1565b500390565b600060a08236031215612fed578081fd5b612ff5612f1c565b8235815261300560208401612a8f565b602082015260408301356001600160401b0380821115613023578384fd5b61302f36838701612a25565b60408401526060850135915080821115613047578384fd5b61305336838701612a25565b6060840152608085013591508082111561306b578384fd5b5061307836828601612962565b60808301525092915050565b600081613093576130936130f1565b506000190190565b600181811c908216806130af57607f821691505b602082108114156130d057634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156130ea576130ea6130f1565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610e2857600080fdfea2646970667358221220867d37c663daf1187a1d45eafdca5e37ecf389669ccacb83c3c1152d304a0def64736f6c63430008040033

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

Validator Index Block Amount
View All Withdrawals

Txn Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]

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