false
false
0

Contract Address Details

0x1000000000000000000000000000000000000003

Contract Name
PriceSubmitter
Creator
Balance
0 FLR
Tokens
Fetching tokens...
Transactions
56,595,330 Transactions
Transfers
0 Transfers
Gas Used
22,813,338,691,758
Last Balance Update
23014434
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
Verified at
2022-07-13T20:51:38.817422Z

./contracts/genesis/implementation/PriceSubmitter.sol

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

import "../../governance/implementation/GovernedAtGenesis.sol";
import "../../addressUpdater/implementation/AddressUpdatable.sol";
import "../interface/IIPriceSubmitter.sol";


/**
 * @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, AddressUpdatable {

    string internal constant ERR_ALREADY_SET = "Already set";
    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 = "FTSO manager only";
    string internal constant ERR_WHITELISTER_ONLY = "Voter whitelister only";
    string internal constant ERR_WRONG_EPOCH_ID = "Wrong epoch id";
    string internal constant ERR_DUPLICATE_SUBMIT_IN_EPOCH = "Duplicate submit in epoch";
    string internal constant ERR_PRICE_INVALID = "Price already revealed or not valid";
    string internal constant ERR_RANDOM_TOO_SMALL = "Too small random number";
    string internal constant ERR_FTSO_INDICES_NOT_INCREASING = "FTSO indices not increasing";

    uint256 public constant MINIMAL_RANDOM = 2**128;    // minimal random value for price submission
    uint256 public constant RANDOM_EPOCH_CYCLIC_BUFFER_SIZE = 50;

    IFtsoRegistryGenesis internal ftsoRegistry; 
    IFtsoManagerGenesis 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;

    mapping(uint256 => mapping(address => bytes32)) internal epochVoterHash;
    uint256[RANDOM_EPOCH_CYCLIC_BUFFER_SIZE] internal randoms;


    modifier onlyFtsoManager {
        require(msg.sender == address(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)) AddressUpdatable(address(0)) {
        /* empty block */
    }

    
    /**
     * @notice Sets the address udpater contract.
     * @param _addressUpdater   The address updater contract.
     */
    function setAddressUpdater(address _addressUpdater) external onlyGovernance {
        require(getAddressUpdater() == address(0), ERR_ALREADY_SET);
        setAddressUpdaterValue(_addressUpdater);
    }
    
    /**
     * 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 hash for current epoch
     * @param _epochId              Target epoch id to which hash is submitted
     * @param _hash                 Hash of ftso indices, prices, random number and voter address
     * @notice Emits HashSubmitted event
     */
    function submitHash(
        uint256 _epochId, 
        bytes32 _hash
    )
        external override
    {
        require(_epochId == ftsoManager.getCurrentPriceEpochId(), ERR_WRONG_EPOCH_ID);
        require(epochVoterHash[_epochId][msg.sender] == 0, ERR_DUPLICATE_SUBMIT_IN_EPOCH);
        require(whitelistedFtsoBitmap[msg.sender] != 0 || trustedAddressesMapping[msg.sender], ERR_NOT_WHITELISTED);

        epochVoterHash[_epochId][msg.sender] = _hash;
        emit HashSubmitted(msg.sender, _epochId, _hash, 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 increasing ftso indices
     * @param _prices               List of submitted prices in USD
     * @param _random               Submitted random number
     * @notice The hash of ftso indices, prices, random number and voter address must be equal to the submitted hash
     * @notice Emits PricesRevealed event
     */
    function revealPrices(
        uint256 _epochId,
        uint256[] memory _ftsoIndices,
        uint256[] memory _prices,
        uint256 _random
    )
        external override
    {
        uint256 length  = _ftsoIndices.length;
        require(length == _prices.length, ERR_ARRAY_LENGTHS);
        require(_random >= MINIMAL_RANDOM, ERR_RANDOM_TOO_SMALL);
        require(epochVoterHash[_epochId][msg.sender] == 
            keccak256(abi.encode(_ftsoIndices, _prices, _random, msg.sender)), 
            ERR_PRICE_INVALID);

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

        // read native VP only once
        uint256 wNatVP = length > 0 ? ftsos[0].wNatVotePowerCached(msg.sender, _epochId) : 0;
        uint256 currentIndex;

        for (uint256 i = 0; i < length; i++) {
            if (i != 0 && currentIndex >= _ftsoIndices[i]) {
                revert(ERR_FTSO_INDICES_NOT_INCREASING);
            }
            currentIndex = _ftsoIndices[i];
            if (allowedBitmask & (1 << currentIndex) == 0) {
                if (!isTrustedAddress) {
                    if (trustedAddressesMapping[msg.sender]) {
                        isTrustedAddress = true;
                    } else {
                        revert(ERR_NOT_WHITELISTED);
                    }
                }
            }
            
            // call reveal price on ftso
            ftsos[i].revealPriceSubmitter(msg.sender, _epochId, _prices[i], wNatVP);
        }
        // prevent price submission from being revealed twice
        delete epochVoterHash[_epochId][msg.sender];

        // random can overflow but still ok
        //slither-disable-next-line weak-prng // not used for random
        randoms[_epochId % RANDOM_EPOCH_CYCLIC_BUFFER_SIZE] += uint256(keccak256(abi.encode(_random, _prices)));

        emit PricesRevealed(msg.sender, _epochId, ftsos, _prices, _random, block.timestamp);
    }

    /**
     * @notice Returns current random number
     * @return Random number
     * @dev Should never revert
     */
    function getCurrentRandom() external view override returns (uint256) {
        uint256 currentEpochId = ftsoManager.getCurrentPriceEpochId();
        if (currentEpochId == 0) {
            return 0;
        }
        //slither-disable-next-line weak-prng // not used for random
        return randoms[(currentEpochId - 1) % RANDOM_EPOCH_CYCLIC_BUFFER_SIZE];
    }

    /**
     * @notice Returns random number of the specified epoch
     * @param _epochId Id of the epoch
     * @return Random number
     */
    function getRandom(uint256 _epochId) external view override returns (uint256) {
        //slither-disable-next-line weak-prng // not used for random
        return randoms[_epochId % RANDOM_EPOCH_CYCLIC_BUFFER_SIZE];
    }
    
    /**
     * 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 (IFtsoManagerGenesis) {
        return ftsoManager;
    }

    /**
     * @notice Implementation of the AddressUpdatable abstract method.
     * @dev 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 _updateContractAddresses(
        bytes32[] memory _contractNameHashes,
        address[] memory _contractAddresses
    )
        internal override
    {
        ftsoRegistry = IFtsoRegistryGenesis(
            _getContractAddress(_contractNameHashes, _contractAddresses, "FtsoRegistry"));
        ftsoManager = IFtsoManagerGenesis(_getContractAddress(_contractNameHashes, _contractAddresses, "FtsoManager"));
        voterWhitelister = _getContractAddress(_contractNameHashes, _contractAddresses, "VoterWhitelister");
    }
}
        

./contracts/genesis/interface/IIPriceSubmitter.sol

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

import "../../userInterfaces/IPriceSubmitter.sol";
interface IIPriceSubmitter is IPriceSubmitter {

    /**
     * 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);
}
          

./contracts/addressUpdater/implementation/AddressUpdatable.sol

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

import "../interface/IIAddressUpdatable.sol";


abstract contract AddressUpdatable is IIAddressUpdatable {

    // https://docs.soliditylang.org/en/v0.8.7/contracts.html#constant-and-immutable-state-variables
    // No storage slot is allocated
    bytes32 internal constant ADDRESS_STORAGE_POSITION = 
        keccak256("flare.diamond.AddressUpdatable.ADDRESS_STORAGE_POSITION");

    modifier onlyAddressUpdater() {
        require (msg.sender == getAddressUpdater(), "only address updater");
        _;
    }

    constructor(address _addressUpdater) {
        setAddressUpdaterValue(_addressUpdater);
    }

    function getAddressUpdater() public view returns (address _addressUpdater) {
        // Only direct constants are allowed in inline assembly, so we assign it here
        bytes32 position = ADDRESS_STORAGE_POSITION;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            _addressUpdater := sload(position)
        }
    }

    /**
     * @notice external method called from AddressUpdater only
     */
    function updateContractAddresses(
        bytes32[] memory _contractNameHashes,
        address[] memory _contractAddresses
    )
        external override
        onlyAddressUpdater
    {
        // update addressUpdater address
        setAddressUpdaterValue(_getContractAddress(_contractNameHashes, _contractAddresses, "AddressUpdater"));
        // update all other addresses
        _updateContractAddresses(_contractNameHashes, _contractAddresses);
    }

    /**
     * @notice virtual method that a contract extending AddressUpdatable must implement
     */
    function _updateContractAddresses(
        bytes32[] memory _contractNameHashes,
        address[] memory _contractAddresses
    ) internal virtual;

    /**
     * @notice helper method to get contract address
     * @dev it reverts if contract name does not exist
     */
    function _getContractAddress(
        bytes32[] memory _nameHashes,
        address[] memory _addresses,
        string memory _nameToFind
    )
        internal pure
        returns(address)
    {
        bytes32 nameHash = keccak256(abi.encode(_nameToFind));
        address a = address(0);
        for (uint256 i = 0; i < _nameHashes.length; i++) {
            if (nameHash == _nameHashes[i]) {
                a = _addresses[i];
                break;
            }
        }
        require(a != address(0), "address zero");
        return a;
    }

    function setAddressUpdaterValue(address _addressUpdater) internal {
        // Only direct constants are allowed in inline assembly, so we assign it here
        bytes32 position = ADDRESS_STORAGE_POSITION;
        // solhint-disable-next-line no-inline-assembly  
        assembly {
            sstore(position, _addressUpdater)
        }
    }
}
          

./contracts/addressUpdater/interface/IIAddressUpdatable.sol

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


interface IIAddressUpdatable {
    /**
     * @notice Updates contract addresses - should be called only from AddressUpdater contract
     * @param _contractNameHashes       list of keccak256(abi.encode(...)) contract names
     * @param _contractAddresses        list of contract addresses corresponding to the contract names
     */
    function updateContractAddresses(
        bytes32[] memory _contractNameHashes,
        address[] memory _contractAddresses
        ) external;
}
          

./contracts/genesis/interface/IFtsoGenesis.sol

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


interface IFtsoGenesis {

    /**
     * @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
     * @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 _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);
}
          

./contracts/genesis/interface/IFtsoManagerGenesis.sol

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


interface IFtsoManagerGenesis {

    function getCurrentPriceEpochId() external view returns (uint256 _priceEpochId);

}
          

./contracts/genesis/interface/IFtsoRegistryGenesis.sol

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

import "./IFtsoGenesis.sol";


interface IFtsoRegistryGenesis {

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

./contracts/governance/implementation/GovernedAtGenesis.sol

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

import "./GovernedBase.sol";


/**
 * @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);
    }
}
          

./contracts/governance/implementation/GovernedBase.sol

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

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


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

    address private initialGovernance;

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

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

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

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

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

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

./contracts/userInterfaces/IGovernanceSettings.sol

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


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

./contracts/userInterfaces/IPriceSubmitter.sol

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

import "../genesis/interface/IFtsoGenesis.sol";
import "../genesis/interface/IFtsoRegistryGenesis.sol";
import "../genesis/interface/IFtsoManagerGenesis.sol";

interface IPriceSubmitter {
    /**
     * Event emitted when hash was submitted through PriceSubmitter.
     * @param submitter the address of the sender
     * @param epochId current price epoch id
     * @param hash the submitted hash
     * @param timestamp current block timestamp
     */
    event HashSubmitted(
        address indexed submitter,
        uint256 indexed epochId,
        bytes32 hash,
        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 random,
        uint256 timestamp
    );
    
    /**
     * @notice Submits hash for current epoch
     * @param _epochId              Target epoch id to which hash is submitted
     * @param _hash                 Hash of ftso indices, prices, random number and voter address
     * @notice Emits HashSubmitted event
     */
    function submitHash(
        uint256 _epochId,
        bytes32 _hash
    ) 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 increasing ftso indices
     * @param _prices               List of submitted prices in USD
     * @param _random               Submitted random number
     * @notice The hash of ftso indices, prices, random number and voter address must be equal to the submitted hash
     * @notice Emits PricesRevealed event
     */
    function revealPrices(
        uint256 _epochId,
        uint256[] memory _ftsoIndices,
        uint256[] memory _prices,
        uint256 _random
    ) 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 (IFtsoManagerGenesis);

    /**
     * @notice Returns current random number
     */
    function getCurrentRandom() external view returns (uint256);
    
    /**
     * @notice Returns random number of the specified epoch
     * @param _epochId              Id of the epoch
     */
    function getRandom(uint256 _epochId) external view returns (uint256);
}
          

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"event","name":"GovernanceCallTimelocked","inputs":[{"type":"bytes4","name":"selector","internalType":"bytes4","indexed":false},{"type":"uint256","name":"allowedAfterTimestamp","internalType":"uint256","indexed":false},{"type":"bytes","name":"encodedCall","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"GovernanceInitialised","inputs":[{"type":"address","name":"initialGovernance","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"GovernedProductionModeEntered","inputs":[{"type":"address","name":"governanceSettings","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"HashSubmitted","inputs":[{"type":"address","name":"submitter","internalType":"address","indexed":true},{"type":"uint256","name":"epochId","internalType":"uint256","indexed":true},{"type":"bytes32","name":"hash","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":"random","internalType":"uint256","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TimelockedGovernanceCallCanceled","inputs":[{"type":"bytes4","name":"selector","internalType":"bytes4","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TimelockedGovernanceCallExecuted","inputs":[{"type":"bytes4","name":"selector","internalType":"bytes4","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MINIMAL_RANDOM","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"RANDOM_EPOCH_CYCLIC_BUFFER_SIZE","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"cancelGovernanceCall","inputs":[{"type":"bytes4","name":"_selector","internalType":"bytes4"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"executeGovernanceCall","inputs":[{"type":"bytes4","name":"_selector","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"_addressUpdater","internalType":"address"}],"name":"getAddressUpdater","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getCurrentRandom","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IFtsoManagerGenesis"}],"name":"getFtsoManager","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IFtsoRegistryGenesis"}],"name":"getFtsoRegistry","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getRandom","inputs":[{"type":"uint256","name":"_epochId","internalType":"uint256"}]},{"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":"view","outputs":[{"type":"address","name":"","internalType":"contract IGovernanceSettings"}],"name":"governanceSettings","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":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"productionMode","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":"_random","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setAddressUpdater","inputs":[{"type":"address","name":"_addressUpdater","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setTrustedAddresses","inputs":[{"type":"address[]","name":"_trustedAddresses","internalType":"address[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"submitHash","inputs":[{"type":"uint256","name":"_epochId","internalType":"uint256"},{"type":"bytes32","name":"_hash","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"switchToProductionMode","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"allowedAfterTimestamp","internalType":"uint256"},{"type":"bytes","name":"encodedCall","internalType":"bytes"}],"name":"timelockedCalls","inputs":[{"type":"bytes4","name":"","internalType":"bytes4"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateContractAddresses","inputs":[{"type":"bytes32[]","name":"_contractNameHashes","internalType":"bytes32[]"},{"type":"address[]","name":"_contractAddresses","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

0x608060405234801561001057600080fd5b506004361061018e5760003560e01c80639d986f91116100de578063c9f960eb11610097578063e17f212e11610071578063e17f212e1461064c578063e2db5a5214610668578063f5a9838314610794578063ffacb84e1461079c5761018e565b8063c9f960eb1461061f578063cd4b691414610627578063d89601fd146106445761018e565b80639d986f91146103f95780639ec2b58114610425578063aea36b53146104c6578063b00c0b76146104ec578063b39c68581461060f578063c0156bcc146106175761018e565b806371e1fad91161014b5780637ac420ad116101255780637ac420ad146103825780638c9d28b6146103a85780638fc6f667146103b05780639d6a890f146103d35761018e565b806371e1fad91461023157806374e6310e1461023957806376794efb146102df5761018e565b80633b56f098146101935780635267a15d146101ad5780635aa6e675146101d15780635ff27079146101d957806362354e031461020257806367fc40291461020a575b600080fd5b61019b6107f4565b60408051918252519081900360200190f35b6101b56107fc565b604080516001600160a01b039092168252519081900360200190f35b6101b5610821565b610200600480360360208110156101ef57600080fd5b50356001600160e01b0319166108b7565b005b6101b5610c0c565b6102006004803603602081101561022057600080fd5b50356001600160e01b031916610c17565b6101b5610cff565b6102606004803603602081101561024f57600080fd5b50356001600160e01b031916610d0e565b6040518083815260200180602001828103825283818151815260200191508051906020019080838360005b838110156102a357818101518382015260200161028b565b50505050905090810190601f1680156102d05780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b610200600480360360408110156102f557600080fd5b810190602081018135600160201b81111561030f57600080fd5b82018360208201111561032157600080fd5b803590602001918460208302840111600160201b8311171561034257600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295505091359250610db4915050565b61019b6004803603602081101561039857600080fd5b50356001600160a01b0316610ecd565b6101b5610ee8565b610200600480360360408110156103c657600080fd5b5080359060200135610ef7565b610200600480360360208110156103e957600080fd5b50356001600160a01b0316611180565b6102006004803603604081101561040f57600080fd5b506001600160a01b038135169060200135611185565b6102006004803603602081101561043b57600080fd5b810190602081018135600160201b81111561045557600080fd5b82018360208201111561046757600080fd5b803590602001918460208302840111600160201b8311171561048857600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611235945050505050565b610200600480360360208110156104dc57600080fd5b50356001600160a01b0316611384565b6102006004803603604081101561050257600080fd5b810190602081018135600160201b81111561051c57600080fd5b82018360208201111561052e57600080fd5b803590602001918460208302840111600160201b8311171561054f57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561059e57600080fd5b8201836020820111156105b057600080fd5b803590602001918460208302840111600160201b831117156105d157600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611451945050505050565b6101b56114fc565b61019b61150b565b6101b5611510565b61019b6004803603602081101561063d57600080fd5b5035611530565b61019b61154a565b6106546115f4565b604080519115158252519081900360200190f35b6102006004803603608081101561067e57600080fd5b81359190810190604081016020820135600160201b81111561069f57600080fd5b8201836020820111156106b157600080fd5b803590602001918460208302840111600160201b831117156106d257600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561072157600080fd5b82018360208201111561073357600080fd5b803590602001918460208302840111600160201b8311171561075457600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295505091359250611604915050565b610200611e1f565b6107a4611ed9565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156107e05781810151838201526020016107c8565b505050509050019250505060405180910390f35b600160801b81565b7f714f205b2abd25bef1d06a1af944e38c113fe6160375c4e1d6d5cf28848e77195490565b60008054600160a81b900460ff16610844576000546001600160a01b03166108b1565b60076001609c1b016001600160a01b031663732524946040518163ffffffff1660e01b815260040160206040518083038186803b15801561088457600080fd5b505afa158015610898573d6000803e3d6000fd5b505050506040513d60208110156108ae57600080fd5b50515b90505b90565b60408051630debfda360e41b8152336004820152905160076001609c1b019163debfda30916024808301926020929190829003018186803b1580156108fb57600080fd5b505afa15801561090f573d6000803e3d6000fd5b505050506040513d602081101561092557600080fd5b5051610968576040805162461bcd60e51b815260206004820152600d60248201526c37b7363c9032bc32b1baba37b960991b604482015290519081900360640190fd5b6001600160e01b03198116600090815260016020526040902080546109d4576040805162461bcd60e51b815260206004820152601a60248201527f74696d656c6f636b3a20696e76616c69642073656c6563746f72000000000000604482015290519081900360640190fd5b8054421015610a2a576040805162461bcd60e51b815260206004820152601960248201527f74696d656c6f636b3a206e6f7420616c6c6f7765642079657400000000000000604482015290519081900360640190fd5b6000816001018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610ac45780601f10610a9957610100808354040283529160200191610ac4565b820191906000526020600020905b815481529060010190602001808311610aa757829003601f168201915b5050506001600160e01b0319861660009081526001602081905260408220828155949550909250610af8915083018261247b565b50506000805460ff60b01b1916600160b01b178155604051825130918491819060208401908083835b60208310610b405780518252601f199092019160209182019101610b21565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610ba2576040519150601f19603f3d011682016040523d82523d6000602084013e610ba7565b606091505b50506000805460ff60b01b19169055604080516001600160e01b03198716815242602082015281519293507fa7326b57fc9cfe267aaea5e7f0b01757154d265620a0585819416ee9ddd2c438929081900390910190a1610c0681611f3b565b50505050565b60076001609c1b0181565b610c1f611f58565b6001600160e01b03198116600090815260016020526040902054610c8a576040805162461bcd60e51b815260206004820152601a60248201527f74696d656c6f636b3a20696e76616c69642073656c6563746f72000000000000604482015290519081900360640190fd5b604080516001600160e01b03198316815242602082015281517f7735b2391c38a81419c513e30ca578db7158eadd7101511b23e221c654d19cf8929181900390910190a16001600160e01b03198116600090815260016020819052604082208281559190610cfa9083018261247b565b505050565b6004546001600160a01b031690565b600160208181526000928352604092839020805481840180548651600296821615610100026000190190911695909504601f81018590048502860185019096528585529094919392909190830182828015610daa5780601f10610d7f57610100808354040283529160200191610daa565b820191906000526020600020905b815481529060010190602001808311610d8d57829003601f168201915b5050505050905082565b600454604080518082019091526016815275566f7465722077686974656c6973746572206f6e6c7960501b6020820152906001600160a01b03163314610e785760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610e3d578181015183820152602001610e25565b50505050905090810190601f168015610e6a5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060005b8251811015610cfa57816001901b1960056000858481518110610e9b57fe5b6020908102919091018101516001600160a01b0316825281019190915260400160002080549091169055600101610e7c565b6001600160a01b031660009081526005602052604090205490565b6002546001600160a01b031690565b600360009054906101000a90046001600160a01b03166001600160a01b03166308a7f4026040518163ffffffff1660e01b815260040160206040518083038186803b158015610f4557600080fd5b505afa158015610f59573d6000803e3d6000fd5b505050506040513d6020811015610f6f57600080fd5b505160408051808201909152600e81526d15dc9bdb99c8195c1bd8da081a5960921b6020820152908314610fe45760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610e3d578181015183820152602001610e25565b506000828152600860209081526040808320338452825291829020548251808401909352601983527f4475706c6963617465207375626d697420696e2065706f63680000000000000091830191909152156110805760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610e3d578181015183820152602001610e25565b50336000908152600560205260409020541515806110ad57503360009081526007602052604090205460ff165b6040518060400160405280600f81526020016e139bdd081dda1a5d195b1a5cdd1959608a1b815250906111215760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610e3d578181015183820152602001610e25565b50600082815260086020908152604080832033808552908352928190208490558051848152429281019290925280518593927f5e2f64e70eafef31c2f48c8ef140b36406531c36ab0faaede30843202c16f6a892908290030190a35050565bfe5b50565b600454604080518082019091526016815275566f7465722077686974656c6973746572206f6e6c7960501b6020820152906001600160a01b0316331461120c5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610e3d578181015183820152602001610e25565b506001600160a01b0390911660009081526005602052604090208054600190921b919091179055565b6003546040805180820190915260118152704654534f206d616e61676572206f6e6c7960781b6020820152906001600160a01b031633146112b75760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610e3d578181015183820152602001610e25565b5060065460005b8181101561131557600060076000600684815481106112d957fe5b6000918252602080832091909101546001600160a01b031683528201929092526040019020805460ff19169115159190911790556001016112be565b5050805160005b818110156113705760016007600085848151811061133657fe5b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905560010161131c565b508151610cfa9060069060208501906124bf565b600054600160b01b900460ff16806113a65750600054600160a81b900460ff16155b15611446576113b3611fb9565b60006113bd6107fc565b6001600160a01b0316146040518060400160405280600b81526020016a105b1c9958591e481cd95d60aa1b815250906114375760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610e3d578181015183820152602001610e25565b5061144181611fee565b611182565b611182600036612012565b6114596107fc565b6001600160a01b0316336001600160a01b0316146114b5576040805162461bcd60e51b815260206004820152601460248201527337b7363c9030b2323932b9b9903ab83230ba32b960611b604482015290519081900360640190fd5b6114ee6114e983836040518060400160405280600e81526020016d20b2323932b9b9aab83230ba32b960911b815250612195565b611fee565b6114f882826122c2565b5050565b6003546001600160a01b031690565b603281565b600073fffec6c83c8bf5c3f4ae0ccf8c45ce20e4560bd76108b1816123c2565b60006009603283066032811061154257fe5b015492915050565b600080600360009054906101000a90046001600160a01b03166001600160a01b03166308a7f4026040518163ffffffff1660e01b815260040160206040518083038186803b15801561159b57600080fd5b505afa1580156115af573d6000803e3d6000fd5b505050506040513d60208110156115c557600080fd5b50519050806115d85760009150506108b4565b60096032600019830106603281106115ec57fe5b015491505090565b600054600160a81b900460ff1681565b8251825160408051808201909152601a81527f4172726179206c656e6774687320646f206e6f74206d61746368000000000000602082015290821461168a5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610e3d578181015183820152602001610e25565b5060408051808201909152601781527f546f6f20736d616c6c2072616e646f6d206e756d6265720000000000000000006020820152600160801b8310156117125760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610e3d578181015183820152602001610e25565b5083838333604051602001808060200180602001858152602001846001600160a01b03168152602001838103835287818151815260200191508051906020019060200280838360005b8381101561177357818101518382015260200161175b565b50505050905001838103825286818151815260200191508051906020019060200280838360005b838110156117b257818101518382015260200161179a565b50505050905001965050505050505060405160208183030381529060405280519060200120600860008781526020019081526020016000206000336001600160a01b03166001600160a01b0316815260200190815260200160002054146040518060600160405280602381526020016125b660239139906118745760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610e3d578181015183820152602001610e25565b506002546040516313968ea760e31b81526020600482018181528751602484015287516000946001600160a01b031693639cb47538938a939283926044019180860191028083838b5b838110156118d55781810151838201526020016118bd565b505050509050019250505060006040518083038186803b1580156118f857600080fd5b505afa15801561190c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561193557600080fd5b8101908080516040519392919084600160201b82111561195457600080fd5b90830190602082018581111561196957600080fd5b82518660208202830111600160201b8211171561198557600080fd5b82525081516020918201928201910280838360005b838110156119b257818101518382015260200161199a565b5050505091909101604090815233600090815260056020529081205495965093508392505050846119e4576000611a7c565b836000815181106119f157fe5b60200260200101516001600160a01b031663f72cab28338b6040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015611a4f57600080fd5b505af1158015611a63573d6000803e3d6000fd5b505050506040513d6020811015611a7957600080fd5b50515b90506000805b86811015611c8f578015801590611aac5750898181518110611aa057fe5b60200260200101518210155b15611b2957604080518082018252601b81527f4654534f20696e6469636573206e6f7420696e6372656173696e6700000000006020808301918252925162461bcd60e51b81526004810193845282516024820152825192939283926044909201919080838360008315610e3d578181015183820152602001610e25565b898181518110611b3557fe5b60200260200101519150816001901b851660001415611bde5783611bde573360009081526007602052604090205460ff1615611b745760019350611bde565b604080518082018252600f81526e139bdd081dda1a5d195b1a5cdd1959608a1b6020808301918252925162461bcd60e51b81526004810193845282516024820152825192939283926044909201919080838360008315610e3d578181015183820152602001610e25565b858181518110611bea57fe5b60200260200101516001600160a01b031663c1f6c36e338d8c8581518110611c0e57fe5b6020026020010151876040518563ffffffff1660e01b815260040180856001600160a01b03168152602001848152602001838152602001828152602001945050505050600060405180830381600087803b158015611c6b57600080fd5b505af1158015611c7f573d6000803e3d6000fd5b505060019092019150611a829050565b5060008a8152600860209081526040808320338452825280832083905580518083018b81528183019283528c5160608301528c518c958e95929493608001928681019202908190849084905b83811015611cf3578181015183820152602001611cdb565b5050505090500193505050506040516020818303038152906040528051906020012060001c600960328c81611d2457fe5b0660328110611d2f57fe5b016000828254019250508190555089336001600160a01b03167fafffa539ac1cad89751c875d871abadc6deb7bd51bf6baea004fc71ca0a48fa5878b8b42604051808060200180602001858152602001848152602001838103835287818151815260200191508051906020019060200280838360005b83811015611dbd578181015183820152602001611da5565b50505050905001838103825286818151815260200191508051906020019060200280838360005b83811015611dfc578181015183820152602001611de4565b50505050905001965050505050505060405180910390a350505050505050505050565b611e27611f58565b600054600160a81b900460ff1615611e86576040805162461bcd60e51b815260206004820152601a60248201527f616c726561647920696e2070726f64756374696f6e206d6f6465000000000000604482015290519081900360640190fd5b60008054600161ff0160a01b031916600160a81b1790556040805160076001609c1b01815290517f83af113638b5422f9e977cebc0aaf0eaf2188eb9a8baae7f9d46c42b33a1560c9181900360200190a1565b60606006805480602002602001604051908101604052809291908181526020018280548015611f3157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611f13575b5050505050905090565b3d604051818101604052816000823e8215611f54578181f35b8181fd5b611f60610821565b6001600160a01b0316336001600160a01b031614611fb7576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920676f7665726e616e636560881b604482015290519081900360640190fd5b565b600054600160b01b900460ff1615611fe657333014611fd457fe5b6000805460ff60b01b19169055611fb7565b611fb7611f58565b7f714f205b2abd25bef1d06a1af944e38c113fe6160375c4e1d6d5cf28848e771955565b61201a611f58565b600082359050600060076001609c1b016001600160a01b0316636221a54b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561206257600080fd5b505afa158015612076573d6000803e3d6000fd5b505050506040513d602081101561208c57600080fd5b505160408051808201825242830180825282516020601f89018190048102820181019094528781529394509290918281019190889088908190840183828082843760009201829052509390945250506001600160e01b0319861681526001602081815260409092208451815584830151805191945061211093928501920190612524565b509050507fed948300a3694aa01d4a6b258bfd664350193d770c0b51f8387277f6d83ea3b68382878760405180856001600160e01b0319168152602001848152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f191690920182900397509095505050505050a15050505050565b600080826040516020018080602001828103825283818151815260200191508051906020019080838360005b838110156121d95781810151838201526020016121c1565b50505050905090810190601f1680156122065780820380516001836020036101000a031916815260200191505b50925050506040516020818303038152906040528051906020012090506000805b865181101561226e5786818151811061223c57fe5b60200260200101518314156122665785818151811061225757fe5b6020026020010151915061226e565b600101612227565b506001600160a01b0381166122b9576040805162461bcd60e51b815260206004820152600c60248201526b61646472657373207a65726f60a01b604482015290519081900360640190fd5b95945050505050565b6122f182826040518060400160405280600c81526020016b4674736f526567697374727960a01b815250612195565b600260006101000a8154816001600160a01b0302191690836001600160a01b0316021790555061234582826040518060400160405280600b81526020016a233a39b7a6b0b730b3b2b960a91b815250612195565b600360006101000a8154816001600160a01b0302191690836001600160a01b0316021790555061239e82826040518060400160405280601081526020016f2b37ba32b92bb434ba32b634b9ba32b960811b815250612195565b600480546001600160a01b0319166001600160a01b03929092169190911790555050565b600054600160a01b900460ff1615612418576040805162461bcd60e51b8152602060048201526014602482015273696e697469616c6973656420213d2066616c736560601b604482015290519081900360640190fd5b60008054600160a01b60ff60a01b19909116176001600160a01b0319166001600160a01b03831690811790915560408051918252517f9789733827840833afc031fb2ef9ab6894271f77bad2085687cf4ae5c7bee4db916020908290030190a150565b50805460018160011615610100020316600290046000825580601f106124a15750611182565b601f01602090049060005260206000209081019061118291906125a0565b828054828255906000526020600020908101928215612514579160200282015b8281111561251457825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906124df565b506125209291506125a0565b5090565b828054600181600116156101000203166002900490600052602060002090601f01602090048101928261255a5760008555612514565b82601f1061257357805160ff1916838001178555612514565b82800160010185558215612514579182015b82811115612514578251825591602001919060010190612585565b5b8082111561252057600081556001016125a156fe507269636520616c72656164792072657665616c6564206f72206e6f742076616c6964a2646970667358221220f6777819e200850a356b0598642d029e083034aaf79d7e264a6cdf6b21e786b364736f6c63430007060033