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