false
false
0

Contract Address Details

0x1000000000000000000000000000000000000003

Contract Name
PriceSubmitter
Creator
Balance
0 CFLR
Tokens
Fetching tokens...
Transactions
4,279,548 Transactions
Transfers
0 Transfers
Gas Used
3,338,606,825,890
Last Balance Update
14249118
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
PriceSubmitter




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




Optimization runs
200
EVM Version
default




Verified at
2022-02-22T12:10:11.025780Z

Contract source code

// Sources flattened with hardhat v2.3.0 https://hardhat.org

// File contracts/governance/implementation/GovernedBase.sol

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


/**
 * @title Governed Base
 * @notice This abstract base class defines behaviors for a governed contract.
 * @dev This class is abstract so that specific behaviors can be defined for the constructor.
 *   Contracts should not be left ungoverned, but not all contract will have a constructor
 *   (for example those pre-defined in genesis).
 **/
abstract contract GovernedBase {
    address public governance;
    address public proposedGovernance;
    bool private initialised;

    event GovernanceProposed(address proposedGovernance);
    event GovernanceUpdated (address oldGovernance, address newGoveranance);

    modifier onlyGovernance () {
        require (msg.sender == governance, "only governance");
        _;
    }

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

    /**
     * @notice First of a two step process for turning over governance to another address.
     * @param _governance The address to propose to receive governance role.
     * @dev Must hold governance to propose another address.
     */
    function proposeGovernance(address _governance) external onlyGovernance {
        proposedGovernance = _governance;
        emit GovernanceProposed(_governance);
    }

    /**
     * @notice Once proposed, claimant can claim the governance role as the second of a two-step process.
     */
    function claimGovernance() external {
        require(msg.sender == proposedGovernance, "not claimaint");

        emit GovernanceUpdated(governance, proposedGovernance);
        governance = proposedGovernance;
        proposedGovernance = address(0);
    }

    /**
     * @notice In a one-step process, turn over governance to another address.
     * @dev Must hold governance to transfer.
     */
    function transferGovernance(address _governance) external onlyGovernance {
        emit GovernanceUpdated(governance, _governance);
        governance = _governance;
        proposedGovernance = address(0);
    }

    /**
     * @notice Initialize the governance address if not first initialized.
     */
    function initialise(address _governance) public virtual {
        require(initialised == false, "initialised != false");

        initialised = true;
        emit GovernanceUpdated(governance, _governance);
        governance = _governance;
        proposedGovernance = address(0);
    }
}


// File contracts/governance/implementation/GovernedAtGenesis.sol

// 
pragma solidity 0.7.6;

/**
 * @title Governed At Genesis
 * @dev This contract enforces a fixed governance address when the constructor
 *  is not executed on a contract (for instance when directly loaded to the genesis block).
 *  This is required to fix governance on a contract when the network starts, at such point
 *  where theoretically no accounts yet exist, and leaving it ungoverned could result in a race
 *  to claim governance by an unauthorized address.
 **/
contract GovernedAtGenesis is GovernedBase {
    constructor(address _governance) GovernedBase(_governance) { }

    /**
     * @notice Set governance to a fixed address when constructor is not called.
     **/
    function initialiseFixedAddress() public virtual returns (address) {
        address governanceAddress = address(0xfffEc6C83c8BF5c3F4AE0cCF8c45CE20E4560BD7);
        
        super.initialise(governanceAddress);
        return governanceAddress;
    }

    /**
     * @notice Disallow initialise to be called
     * @param _governance The governance address for initial claiming
     **/
    // solhint-disable-next-line no-unused-vars
    function initialise(address _governance) public override pure {
        assert(false);
    }
}


// File contracts/genesis/interface/IFtsoGenesis.sol

// 
pragma solidity 0.7.6;


interface IFtsoGenesis {
    
    /**
     * @notice Submits price hash for current epoch - only price submitter
     * @param _sender               Sender address
     * @param _epochId              Target epoch id to which hashes are submitted
     * @param _hash                 Hashed price and random number
     * @notice Emits PriceHashSubmitted event. 
     */
    function submitPriceHashSubmitter(address _sender, uint256 _epochId, bytes32 _hash) external;

    /**
     * @notice Reveals submitted price during epoch reveal period - only price submitter
     * @param _voter                Voter address
     * @param _epochId              Id of the epoch in which the price hash was submitted
     * @param _price                Submitted price in USD
     * @param _random               Submitted random number
     * @notice The hash of _price and _random must be equal to the submitted hash
     * @notice Emits PriceRevealed event
     */
    function revealPriceSubmitter(
        address _voter,
        uint256 _epochId,
        uint256 _price,
        uint256 _random,
        uint256 _wNatVP
    ) external;

    /**
     * @notice Get (and cache) wNat vote power for specified voter and given epoch id
     * @param _voter                Voter address
     * @param _epochId              Id of the epoch in which the price hash was submitted
     * @return wNat vote power
     */
    function wNatVotePowerCached(address _voter, uint256 _epochId) external returns (uint256);
}


// File contracts/genesis/interface/IFtsoRegistryGenesis.sol

// 
pragma solidity 0.7.6;

interface IFtsoRegistryGenesis {

    function getFtsos(uint256[] memory _indices) external view returns(IFtsoGenesis[] memory _ftsos);
}


// File contracts/userInterfaces/IPriceSubmitter.sol

// 
pragma solidity 0.7.6;


interface IPriceSubmitter {
    /**
     * Event emitted when price hashes were submitted through PriceSubmitter.
     * @param submitter the address of the sender
     * @param epochId current price epoch id
     * @param ftsos array of ftsos that correspond to the indexes in call
     * @param hashes the submitted hashes
     * @param timestamp current block timestamp
     */
    event PriceHashesSubmitted(
        address indexed submitter,
        uint256 indexed epochId,
        IFtsoGenesis[] ftsos,
        bytes32[] hashes,
        uint256 timestamp
    );

    /**
     * Event emitted when prices were revealed through PriceSubmitter.
     * @param voter the address of the sender
     * @param epochId id of the epoch in which the price hash was submitted
     * @param ftsos array of ftsos that correspond to the indexes in the call
     * @param prices the submitted prices
     * @param timestamp current block timestamp
     */
    event PricesRevealed(
        address indexed voter,
        uint256 indexed epochId,
        IFtsoGenesis[] ftsos,
        uint256[] prices,
        uint256[] randoms,
        uint256 timestamp
    );
    
    /**
     * @notice Submits price hashes for current epoch
     * @param _epochId              Target epoch id to which hashes are submitted
     * @param _ftsoIndices          List of ftso indices
     * @param _hashes               List of hashed price and random number
     * @notice Emits PriceHashesSubmitted event
     */
    function submitPriceHashes(
        uint256 _epochId,
        uint256[] memory _ftsoIndices,
        bytes32[] memory _hashes
    ) external;

    /**
     * @notice Reveals submitted prices during epoch reveal period
     * @param _epochId              Id of the epoch in which the price hashes was submitted
     * @param _ftsoIndices          List of ftso indices
     * @param _prices               List of submitted prices in USD
     * @param _randoms              List of submitted random numbers
     * @notice The hash of _price and _random must be equal to the submitted hash
     * @notice Emits PricesRevealed event
     */
    function revealPrices(
        uint256 _epochId,
        uint256[] memory _ftsoIndices,
        uint256[] memory _prices,
        uint256[] memory _randoms
    ) external;

    /**
     * Returns bitmap of all ftso's for which `_voter` is allowed to submit prices/hashes.
     * If voter is allowed to vote for ftso at index (see *_FTSO_INDEX), the corrsponding
     * bit in the result will be 1.
     */    
    function voterWhitelistBitmap(address _voter) external view returns (uint256);

    function getVoterWhitelister() external view returns (address);
    function getFtsoRegistry() external view returns (IFtsoRegistryGenesis);
    function getFtsoManager() external view returns (address);
}


// File contracts/genesis/interface/IIPriceSubmitter.sol

// 
pragma solidity 0.7.6;

interface IIPriceSubmitter is IPriceSubmitter {

    /**
     * Sets ftso registry, voter whitelist and ftso manager contracts.
     * Only governance can call this method.
     * If replacing the registry or the whitelist and the old one is not empty, make sure to replicate the state,
     * otherwise internal whitelist bitmaps won't match.
     */
    function setContractAddresses(
        IFtsoRegistryGenesis _ftsoRegistry,
        address _voterWhitelister,
        address _ftsoManager
    ) external;

    /**
     * Set trusted addresses that are always allowed to submit and reveal.
     * Only ftso manager can call this method.
     */
    function setTrustedAddresses(address[] memory _trustedAddresses) external;

    /**
     * Called from whitelister when new voter has been whitelisted.
     */
    function voterWhitelisted(address _voter, uint256 _ftsoIndex) external;
    
    /**
     * Called from whitelister when one or more voters have been removed.
     */
    function votersRemovedFromWhitelist(address[] memory _voters, uint256 _ftsoIndex) external;

    /**
     * Returns a list of trusted addresses that are always allowed to submit and reveal.
     */
    function getTrustedAddresses() external view returns (address[] memory);
}


// File contracts/genesis/implementation/PriceSubmitter.sol

// 
pragma solidity 0.7.6;


/**
 * @title Price submitter
 * @notice A contract used to submit/reveal prices to multiple Flare Time Series Oracles in one transaction
 */
contract PriceSubmitter is IIPriceSubmitter, GovernedAtGenesis {

    string internal constant ERR_ARRAY_LENGTHS = "Array lengths do not match";
    string internal constant ERR_NOT_WHITELISTED = "Not whitelisted";
    string internal constant ERR_FTSO_MANAGER_ONLY = "FTSOManager only";
    string internal constant ERR_WHITELISTER_ONLY = "Voter whitelister only";


    IFtsoRegistryGenesis internal ftsoRegistry; 
    address internal ftsoManager;
    address internal voterWhitelister;

    // Bit at index `i` corresponds to being whitelisted for vote on ftso at index `i`
    mapping(address => uint256) internal whitelistedFtsoBitmap;
    
    address[] internal trustedAddresses;
    // for checking addresses at submit/reveal
    mapping(address => bool) internal trustedAddressesMapping;

    
    modifier onlyFtsoManager {
        require(msg.sender == ftsoManager, ERR_FTSO_MANAGER_ONLY);
        _;
    }

    modifier onlyWhitelister {
        require(msg.sender == voterWhitelister, ERR_WHITELISTER_ONLY);
        _;
    }

    /**
     * @dev This constructor should contain no code as this contract is pre-loaded into the genesis block.
     *   The super constructor is called for testing convenience.
     */
    constructor() GovernedAtGenesis(address(0)) {
        /* empty block */
    }

    /**
     * Sets ftso registry, voter whitelist and ftso manager contracts.
     * Only governance can call this method.
     * If replacing the registry or the whitelist and the old one is not empty, make sure to replicate the state,
     * otherwise internal whitelist bitmaps won't match.
     */
    function setContractAddresses(
        IFtsoRegistryGenesis _ftsoRegistry,
        address _voterWhitelister,
        address _ftsoManager
    ) 
        external override 
        onlyGovernance
    {
        ftsoRegistry = _ftsoRegistry;
        voterWhitelister = _voterWhitelister;
        ftsoManager = _ftsoManager;
    }
    
    /**
     * Set trusted addresses that are always allowed to submit and reveal.
     * Only ftso manager can call this method.
     */
    function setTrustedAddresses(address[] memory _trustedAddresses) external override onlyFtsoManager {
        // remove old addresses mapping
        uint256 len = trustedAddresses.length;
        for (uint256 i = 0; i < len; i++) {
            trustedAddressesMapping[trustedAddresses[i]] = false;
        }
        // set new addresses mapping
        len = _trustedAddresses.length;
        for (uint256 i = 0; i < len; i++) {
            trustedAddressesMapping[_trustedAddresses[i]] = true;
        }
        trustedAddresses = _trustedAddresses;
    }
    
    /**
     * Called from whitelister when new voter has been whitelisted.
     */
    function voterWhitelisted(address _voter, uint256 _ftsoIndex) external override onlyWhitelister {
        whitelistedFtsoBitmap[_voter] |= 1 << _ftsoIndex;
    }
    
    /**
     * Called from whitelister when one or more voters have been removed.
     */
    function votersRemovedFromWhitelist(address[] memory _removedVoters, uint256 _ftsoIndex) 
        external override 
        onlyWhitelister
    {
        for (uint256 i = 0; i < _removedVoters.length; i++) {
            whitelistedFtsoBitmap[_removedVoters[i]]  &= ~(1 << _ftsoIndex);
        }
    }
    
    /**
     * @notice Submits price hashes for current epoch
     * @param _ftsoIndices          List of ftso indices
     * @param _hashes               List of hashed price and random number
     * @notice Emits PriceHashesSubmitted event
     */
    function submitPriceHashes(
        uint256 _epochId, 
        uint256[] memory _ftsoIndices, 
        bytes32[] memory _hashes
    ) external override {
        // Submit the prices
        uint256 length = _ftsoIndices.length;
        require(length == _hashes.length, ERR_ARRAY_LENGTHS);

        IFtsoGenesis[] memory ftsos = ftsoRegistry.getFtsos(_ftsoIndices);
        uint256 allowedBitmask = whitelistedFtsoBitmap[msg.sender];
        bool isTrustedAddress = false;

        for (uint256 i = 0; i < length; i++) {
            uint256 ind = _ftsoIndices[i];
            if (allowedBitmask & (1 << ind) == 0) {
                if (!isTrustedAddress) {
                    if (trustedAddressesMapping[msg.sender]) {
                        isTrustedAddress = true;
                    } else {
                        revert(ERR_NOT_WHITELISTED);
                    }
                }
            }
            ftsos[i].submitPriceHashSubmitter(msg.sender, _epochId, _hashes[i]);
        }
        emit PriceHashesSubmitted(msg.sender, _epochId, ftsos, _hashes, block.timestamp);
    }

    /**
     * @notice Reveals submitted prices during epoch reveal period
     * @param _epochId              Id of the epoch in which the price hashes was submitted
     * @param _ftsoIndices          List of ftso indices
     * @param _prices               List of submitted prices in USD
     * @param _randoms              List of submitted random numbers
     * @notice The hash of _price and _random must be equal to the submitted hash
     * @notice Emits PricesRevealed event
     */
    function revealPrices(
        uint256 _epochId,
        uint256[] memory _ftsoIndices,
        uint256[] memory _prices,
        uint256[] memory _randoms
    )
        external override
    {
        uint256 length  = _ftsoIndices.length;
        require(length == _prices.length, ERR_ARRAY_LENGTHS);
        require(length == _randoms.length, ERR_ARRAY_LENGTHS);

        IFtsoGenesis[] memory ftsos = ftsoRegistry.getFtsos(_ftsoIndices);
        uint256 allowedBitmask = whitelistedFtsoBitmap[msg.sender];
        bool isTrustedAddress = false;

        uint256 wNatVP = uint256(-1);

        for (uint256 i = 0; i < length; i++) {
            uint256 ind = _ftsoIndices[i];
            if (allowedBitmask & (1 << ind) == 0) {
                if (!isTrustedAddress) {
                    if (trustedAddressesMapping[msg.sender]) {
                        isTrustedAddress = true;
                    } else {
                        revert(ERR_NOT_WHITELISTED);
                    }
                }
            }
            // read native VP only once
            if (wNatVP == uint256(-1)) {
                wNatVP = ftsos[i].wNatVotePowerCached(msg.sender, _epochId);
            }
            // call reveal price on ftso
            ftsos[i].revealPriceSubmitter(msg.sender, _epochId, _prices[i], _randoms[i], wNatVP);
        }
        emit PricesRevealed(msg.sender, _epochId, ftsos, _prices, _randoms, block.timestamp);
    }
    
    /**
     * Returns bitmap of all ftso's for which `_voter` is allowed to submit prices/hashes.
     * If voter is allowed to vote for ftso at index (see *_FTSO_INDEX), the corrsponding
     * bit in the result will be 1.
     */    
    function voterWhitelistBitmap(address _voter) external view override returns (uint256) {
        return whitelistedFtsoBitmap[_voter];
    }
    
    function getTrustedAddresses() external view override returns (address[] memory) {
        return trustedAddresses;
    }

    function getVoterWhitelister() external view override returns (address) {
        return voterWhitelister;
    }

    function getFtsoRegistry() external view override returns (IFtsoRegistryGenesis) {
        return ftsoRegistry;
    }
    
    function getFtsoManager() external view override returns (address) {
        return ftsoManager;
    }
}
        

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"event","name":"GovernanceProposed","inputs":[{"type":"address","name":"proposedGovernance","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"GovernanceUpdated","inputs":[{"type":"address","name":"oldGovernance","internalType":"address","indexed":false},{"type":"address","name":"newGoveranance","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"PriceHashesSubmitted","inputs":[{"type":"address","name":"submitter","internalType":"address","indexed":true},{"type":"uint256","name":"epochId","internalType":"uint256","indexed":true},{"type":"address[]","name":"ftsos","internalType":"contract IFtsoGenesis[]","indexed":false},{"type":"bytes32[]","name":"hashes","internalType":"bytes32[]","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"PricesRevealed","inputs":[{"type":"address","name":"voter","internalType":"address","indexed":true},{"type":"uint256","name":"epochId","internalType":"uint256","indexed":true},{"type":"address[]","name":"ftsos","internalType":"contract IFtsoGenesis[]","indexed":false},{"type":"uint256[]","name":"prices","internalType":"uint256[]","indexed":false},{"type":"uint256[]","name":"randoms","internalType":"uint256[]","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"claimGovernance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getFtsoManager","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IFtsoRegistryGenesis"}],"name":"getFtsoRegistry","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getTrustedAddresses","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getVoterWhitelister","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"governance","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[],"name":"initialise","inputs":[{"type":"address","name":"_governance","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"initialiseFixedAddress","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"proposeGovernance","inputs":[{"type":"address","name":"_governance","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"proposedGovernance","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"revealPrices","inputs":[{"type":"uint256","name":"_epochId","internalType":"uint256"},{"type":"uint256[]","name":"_ftsoIndices","internalType":"uint256[]"},{"type":"uint256[]","name":"_prices","internalType":"uint256[]"},{"type":"uint256[]","name":"_randoms","internalType":"uint256[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setContractAddresses","inputs":[{"type":"address","name":"_ftsoRegistry","internalType":"contract IFtsoRegistryGenesis"},{"type":"address","name":"_voterWhitelister","internalType":"address"},{"type":"address","name":"_ftsoManager","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setTrustedAddresses","inputs":[{"type":"address[]","name":"_trustedAddresses","internalType":"address[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"submitPriceHashes","inputs":[{"type":"uint256","name":"_epochId","internalType":"uint256"},{"type":"uint256[]","name":"_ftsoIndices","internalType":"uint256[]"},{"type":"bytes32[]","name":"_hashes","internalType":"bytes32[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferGovernance","inputs":[{"type":"address","name":"_governance","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"voterWhitelistBitmap","inputs":[{"type":"address","name":"_voter","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"voterWhitelisted","inputs":[{"type":"address","name":"_voter","internalType":"address"},{"type":"uint256","name":"_ftsoIndex","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"votersRemovedFromWhitelist","inputs":[{"type":"address[]","name":"_removedVoters","internalType":"address[]"},{"type":"uint256","name":"_ftsoIndex","internalType":"uint256"}]}]
              

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106101165760003560e01c80639d6a890f116100a2578063c373a08e11610071578063c373a08e1461051b578063c5adc53914610541578063c9f960eb1461066b578063d38bfff414610673578063ffacb84e1461069957610116565b80639d6a890f146104205780639d986f91146104465780639ec2b58114610472578063b39c68581461051357610116565b806371e1fad9116100e957806371e1fad9146102fd57806376794efb146103055780637ac420ad146103a85780638ab63380146103e05780638c9d28b61461041857610116565b80635aa6e6751461011b5780635d36b1901461013f57806360848b441461014957806360f7ac97146102f5575b600080fd5b6101236106f1565b604080516001600160a01b039092168252519081900360200190f35b610147610700565b005b6101476004803603608081101561015f57600080fd5b81359190810190604081016020820135600160201b81111561018057600080fd5b82018360208201111561019257600080fd5b803590602001918460208302840111600160201b831117156101b357600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561020257600080fd5b82018360208201111561021457600080fd5b803590602001918460208302840111600160201b8311171561023557600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561028457600080fd5b82018360208201111561029657600080fd5b803590602001918460208302840111600160201b831117156102b757600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506107c2945050505050565b610123610dbe565b610123610dcd565b6101476004803603604081101561031b57600080fd5b810190602081018135600160201b81111561033557600080fd5b82018360208201111561034757600080fd5b803590602001918460208302840111600160201b8311171561036857600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295505091359250610ddc915050565b6103ce600480360360208110156103be57600080fd5b50356001600160a01b0316610ebd565b60408051918252519081900360200190f35b610147600480360360608110156103f657600080fd5b506001600160a01b038135811691602081013582169160409091013516610ed8565b610123610f68565b6101476004803603602081101561043657600080fd5b50356001600160a01b0316610f77565b6101476004803603604081101561045c57600080fd5b506001600160a01b038135169060200135610f79565b6101476004803603602081101561048857600080fd5b810190602081018135600160201b8111156104a257600080fd5b8201836020820111156104b457600080fd5b803590602001918460208302840111600160201b831117156104d557600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611029945050505050565b610123611177565b6101476004803603602081101561053157600080fd5b50356001600160a01b0316611186565b6101476004803603606081101561055757600080fd5b81359190810190604081016020820135600160201b81111561057857600080fd5b82018360208201111561058a57600080fd5b803590602001918460208302840111600160201b831117156105ab57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b8111156105fa57600080fd5b82018360208201111561060c57600080fd5b803590602001918460208302840111600160201b8311171561062d57600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092955061122b945050505050565b6101236115e6565b6101476004803603602081101561068957600080fd5b50356001600160a01b031661160b565b6106a16116cd565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156106dd5781810151838201526020016106c5565b505050509050019250505060405180910390f35b6000546001600160a01b031681565b6001546001600160a01b0316331461074f576040805162461bcd60e51b815260206004820152600d60248201526c1b9bdd0818db185a5b585a5b9d609a1b604482015290519081900360640190fd5b600054600154604080516001600160a01b03938416815292909116602083015280517f434a2db650703b36c824e745330d6397cdaa9ee2cc891a4938ae853e1c50b68d9281900390910190a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b8251825160408051808201909152601a815279082e4e4c2f240d8cadccee8d0e640c8de40dcdee840dac2e8c6d60331b60208201529082146108825760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561084757818101518382015260200161082f565b50505050905090810190601f1680156108745780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50815181146040518060400160405280601a815260200179082e4e4c2f240d8cadccee8d0e640c8de40dcdee840dac2e8c6d60331b815250906109065760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561084757818101518382015260200161082f565b506002546040516313968ea760e31b81526020600482018181528751602484015287516000946001600160a01b031693639cb47538938a939283926044019180860191028083838b5b8381101561096757818101518382015260200161094f565b505050509050019250505060006040518083038186803b15801561098a57600080fd5b505afa15801561099e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156109c757600080fd5b8101908080516040519392919084600160201b8211156109e657600080fd5b9083019060208201858111156109fb57600080fd5b82518660208202830111600160201b82111715610a1757600080fd5b82525081516020918201928201910280838360005b83811015610a44578181015183820152602001610a2c565b5050505091909101604090815233600090815260056020529081205495965093506000199250839150505b85811015610c9e576000898281518110610a8557fe5b60200260200101519050806001901b851660001415610b2e5783610b2e573360009081526007602052604090205460ff1615610ac45760019350610b2e565b604080518082018252600f81526e139bdd081dda1a5d195b1a5cdd1959608a1b6020808301918252925162461bcd60e51b8152600481019384528251602482015282519293928392604490920191908083836000831561084757818101518382015260200161082f565b600019831415610bd157858281518110610b4457fe5b60200260200101516001600160a01b031663f72cab28338d6040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015610ba257600080fd5b505af1158015610bb6573d6000803e3d6000fd5b505050506040513d6020811015610bcc57600080fd5b505192505b858281518110610bdd57fe5b60200260200101516001600160a01b03166355f7b69b338d8c8681518110610c0157fe5b60200260200101518c8781518110610c1557fe5b6020026020010151886040518663ffffffff1660e01b815260040180866001600160a01b0316815260200185815260200184815260200183815260200182815260200195505050505050600060405180830381600087803b158015610c7957600080fd5b505af1158015610c8d573d6000803e3d6000fd5b505060019093019250610a6f915050565b5088336001600160a01b03167fa32444a31df2f9a116229eec3193d223a6bad89f7670ff17b8e5c7014a377da1868a8a4260405180806020018060200180602001858152602001848103845288818151815260200191508051906020019060200280838360005b83811015610d1d578181015183820152602001610d05565b50505050905001848103835287818151815260200191508051906020019060200280838360005b83811015610d5c578181015183820152602001610d44565b50505050905001848103825286818151815260200191508051906020019060200280838360005b83811015610d9b578181015183820152602001610d83565b5050505090500197505050505050505060405180910390a3505050505050505050565b6001546001600160a01b031681565b6004546001600160a01b031690565b600454604080518082019091526016815275566f7465722077686974656c6973746572206f6e6c7960501b6020820152906001600160a01b03163314610e635760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561084757818101518382015260200161082f565b5060005b8251811015610eb857816001901b1960056000858481518110610e8657fe5b6020908102919091018101516001600160a01b0316825281019190915260400160002080549091169055600101610e67565b505050565b6001600160a01b031660009081526005602052604090205490565b6000546001600160a01b03163314610f29576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920676f7665726e616e636560881b604482015290519081900360640190fd5b600280546001600160a01b039485166001600160a01b031991821617909155600480549385169382169390931790925560038054919093169116179055565b6002546001600160a01b031690565bfe5b600454604080518082019091526016815275566f7465722077686974656c6973746572206f6e6c7960501b6020820152906001600160a01b031633146110005760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561084757818101518382015260200161082f565b506001600160a01b0390911660009081526005602052604090208054600190921b919091179055565b60035460408051808201909152601081526f4654534f4d616e61676572206f6e6c7960801b6020820152906001600160a01b031633146110aa5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561084757818101518382015260200161082f565b5060065460005b8181101561110857600060076000600684815481106110cc57fe5b6000918252602080832091909101546001600160a01b031683528201929092526040019020805460ff19169115159190911790556001016110b1565b5050805160005b818110156111635760016007600085848151811061112957fe5b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905560010161110f565b508151610eb8906006906020850190611809565b6003546001600160a01b031690565b6000546001600160a01b031633146111d7576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920676f7665726e616e636560881b604482015290519081900360640190fd5b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f1f95fb40be3a947982072902a887b521248d1d8931a39eb38f84f4d6fd758b699181900360200190a150565b8151815160408051808201909152601a815279082e4e4c2f240d8cadccee8d0e640c8de40dcdee840dac2e8c6d60331b60208201529082146112ae5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561084757818101518382015260200161082f565b506002546040516313968ea760e31b81526020600482018181528651602484015286516000946001600160a01b031693639cb475389389939283926044019180860191028083838b5b8381101561130f5781810151838201526020016112f7565b505050509050019250505060006040518083038186803b15801561133257600080fd5b505afa158015611346573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561136f57600080fd5b8101908080516040519392919084600160201b82111561138e57600080fd5b9083019060208201858111156113a357600080fd5b82518660208202830111600160201b821117156113bf57600080fd5b82525081516020918201928201910280838360005b838110156113ec5781810151838201526020016113d4565b50505050919091016040908152336000908152600560205290812054959650935083925050505b8481101561150e57600087828151811061142957fe5b60200260200101519050806001901b8416600014156114645782611464573360009081526007602052604090205460ff1615610ac457600192505b84828151811061147057fe5b60200260200101516001600160a01b03166327bd2ad5338b8a868151811061149457fe5b60200260200101516040518463ffffffff1660e01b815260040180846001600160a01b031681526020018381526020018281526020019350505050600060405180830381600087803b1580156114e957600080fd5b505af11580156114fd573d6000803e3d6000fd5b505060019093019250611413915050565b5086336001600160a01b03167f90c022ade239639b1f8c4ebb8a76df5e03a7129df46cf9bcdae3c1450ea35434858842604051808060200180602001848152602001838103835286818151815260200191508051906020019060200280838360005b83811015611588578181015183820152602001611570565b50505050905001838103825285818151815260200191508051906020019060200280838360005b838110156115c75781810151838201526020016115af565b505050509050019550505050505060405180910390a350505050505050565b600073fffec6c83c8bf5c3f4ae0ccf8c45ce20e4560bd76116068161172f565b905090565b6000546001600160a01b0316331461165c576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920676f7665726e616e636560881b604482015290519081900360640190fd5b600054604080516001600160a01b039283168152918316602083015280517f434a2db650703b36c824e745330d6397cdaa9ee2cc891a4938ae853e1c50b68d9281900390910190a1600080546001600160a01b039092166001600160a01b0319928316179055600180549091169055565b6060600680548060200260200160405190810160405280929190818152602001828054801561172557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611707575b5050505050905090565b600154600160a01b900460ff1615611785576040805162461bcd60e51b8152602060048201526014602482015273696e697469616c6973656420213d2066616c736560601b604482015290519081900360640190fd5b6001805460ff60a01b1916600160a01b179055600054604080516001600160a01b039283168152918316602083015280517f434a2db650703b36c824e745330d6397cdaa9ee2cc891a4938ae853e1c50b68d9281900390910190a1600080546001600160a01b039092166001600160a01b0319928316179055600180549091169055565b82805482825590600052602060002090810192821561185e579160200282015b8281111561185e57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190611829565b5061186a92915061186e565b5090565b5b8082111561186a576000815560010161186f56fea2646970667358221220c1d73dd5d713527b4b18f6ca6d3d915fe356fa5425b5776172fa3bf91a5476e564736f6c63430007060033