Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- PriceSubmitter
- Optimization enabled
- true
- Compiler version
- v0.7.6+commit.7338295f
- Optimization runs
- 200
- EVM Version
- default
- Verified at
- 2022-02-22T12:10:11.025780Z
Contract source code
// Sources flattened with hardhat v2.3.0 https://hardhat.org // File contracts/governance/implementation/GovernedBase.sol // SPDX-License-Identifier: MIT pragma solidity 0.7.6; /** * @title Governed Base * @notice This abstract base class defines behaviors for a governed contract. * @dev This class is abstract so that specific behaviors can be defined for the constructor. * Contracts should not be left ungoverned, but not all contract will have a constructor * (for example those pre-defined in genesis). **/ abstract contract GovernedBase { address public governance; address public proposedGovernance; bool private initialised; event GovernanceProposed(address proposedGovernance); event GovernanceUpdated (address oldGovernance, address newGoveranance); modifier onlyGovernance () { require (msg.sender == governance, "only governance"); _; } constructor(address _governance) { if (_governance != address(0)) { initialise(_governance); } } /** * @notice First of a two step process for turning over governance to another address. * @param _governance The address to propose to receive governance role. * @dev Must hold governance to propose another address. */ function proposeGovernance(address _governance) external onlyGovernance { proposedGovernance = _governance; emit GovernanceProposed(_governance); } /** * @notice Once proposed, claimant can claim the governance role as the second of a two-step process. */ function claimGovernance() external { require(msg.sender == proposedGovernance, "not claimaint"); emit GovernanceUpdated(governance, proposedGovernance); governance = proposedGovernance; proposedGovernance = address(0); } /** * @notice In a one-step process, turn over governance to another address. * @dev Must hold governance to transfer. */ function transferGovernance(address _governance) external onlyGovernance { emit GovernanceUpdated(governance, _governance); governance = _governance; proposedGovernance = address(0); } /** * @notice Initialize the governance address if not first initialized. */ function initialise(address _governance) public virtual { require(initialised == false, "initialised != false"); initialised = true; emit GovernanceUpdated(governance, _governance); governance = _governance; proposedGovernance = address(0); } } // File contracts/governance/implementation/GovernedAtGenesis.sol // pragma solidity 0.7.6; /** * @title Governed At Genesis * @dev This contract enforces a fixed governance address when the constructor * is not executed on a contract (for instance when directly loaded to the genesis block). * This is required to fix governance on a contract when the network starts, at such point * where theoretically no accounts yet exist, and leaving it ungoverned could result in a race * to claim governance by an unauthorized address. **/ contract GovernedAtGenesis is GovernedBase { constructor(address _governance) GovernedBase(_governance) { } /** * @notice Set governance to a fixed address when constructor is not called. **/ function initialiseFixedAddress() public virtual returns (address) { address governanceAddress = address(0xfffEc6C83c8BF5c3F4AE0cCF8c45CE20E4560BD7); super.initialise(governanceAddress); return governanceAddress; } /** * @notice Disallow initialise to be called * @param _governance The governance address for initial claiming **/ // solhint-disable-next-line no-unused-vars function initialise(address _governance) public override pure { assert(false); } } // File contracts/genesis/interface/IFtsoGenesis.sol // pragma solidity 0.7.6; interface IFtsoGenesis { /** * @notice Submits price hash for current epoch - only price submitter * @param _sender Sender address * @param _epochId Target epoch id to which hashes are submitted * @param _hash Hashed price and random number * @notice Emits PriceHashSubmitted event. */ function submitPriceHashSubmitter(address _sender, uint256 _epochId, bytes32 _hash) external; /** * @notice Reveals submitted price during epoch reveal period - only price submitter * @param _voter Voter address * @param _epochId Id of the epoch in which the price hash was submitted * @param _price Submitted price in USD * @param _random Submitted random number * @notice The hash of _price and _random must be equal to the submitted hash * @notice Emits PriceRevealed event */ function revealPriceSubmitter( address _voter, uint256 _epochId, uint256 _price, uint256 _random, uint256 _wNatVP ) external; /** * @notice Get (and cache) wNat vote power for specified voter and given epoch id * @param _voter Voter address * @param _epochId Id of the epoch in which the price hash was submitted * @return wNat vote power */ function wNatVotePowerCached(address _voter, uint256 _epochId) external returns (uint256); } // File contracts/genesis/interface/IFtsoRegistryGenesis.sol // pragma solidity 0.7.6; interface IFtsoRegistryGenesis { function getFtsos(uint256[] memory _indices) external view returns(IFtsoGenesis[] memory _ftsos); } // File contracts/userInterfaces/IPriceSubmitter.sol // pragma solidity 0.7.6; interface IPriceSubmitter { /** * Event emitted when price hashes were submitted through PriceSubmitter. * @param submitter the address of the sender * @param epochId current price epoch id * @param ftsos array of ftsos that correspond to the indexes in call * @param hashes the submitted hashes * @param timestamp current block timestamp */ event PriceHashesSubmitted( address indexed submitter, uint256 indexed epochId, IFtsoGenesis[] ftsos, bytes32[] hashes, uint256 timestamp ); /** * Event emitted when prices were revealed through PriceSubmitter. * @param voter the address of the sender * @param epochId id of the epoch in which the price hash was submitted * @param ftsos array of ftsos that correspond to the indexes in the call * @param prices the submitted prices * @param timestamp current block timestamp */ event PricesRevealed( address indexed voter, uint256 indexed epochId, IFtsoGenesis[] ftsos, uint256[] prices, uint256[] randoms, uint256 timestamp ); /** * @notice Submits price hashes for current epoch * @param _epochId Target epoch id to which hashes are submitted * @param _ftsoIndices List of ftso indices * @param _hashes List of hashed price and random number * @notice Emits PriceHashesSubmitted event */ function submitPriceHashes( uint256 _epochId, uint256[] memory _ftsoIndices, bytes32[] memory _hashes ) external; /** * @notice Reveals submitted prices during epoch reveal period * @param _epochId Id of the epoch in which the price hashes was submitted * @param _ftsoIndices List of ftso indices * @param _prices List of submitted prices in USD * @param _randoms List of submitted random numbers * @notice The hash of _price and _random must be equal to the submitted hash * @notice Emits PricesRevealed event */ function revealPrices( uint256 _epochId, uint256[] memory _ftsoIndices, uint256[] memory _prices, uint256[] memory _randoms ) external; /** * Returns bitmap of all ftso's for which `_voter` is allowed to submit prices/hashes. * If voter is allowed to vote for ftso at index (see *_FTSO_INDEX), the corrsponding * bit in the result will be 1. */ function voterWhitelistBitmap(address _voter) external view returns (uint256); function getVoterWhitelister() external view returns (address); function getFtsoRegistry() external view returns (IFtsoRegistryGenesis); function getFtsoManager() external view returns (address); } // File contracts/genesis/interface/IIPriceSubmitter.sol // pragma solidity 0.7.6; interface IIPriceSubmitter is IPriceSubmitter { /** * Sets ftso registry, voter whitelist and ftso manager contracts. * Only governance can call this method. * If replacing the registry or the whitelist and the old one is not empty, make sure to replicate the state, * otherwise internal whitelist bitmaps won't match. */ function setContractAddresses( IFtsoRegistryGenesis _ftsoRegistry, address _voterWhitelister, address _ftsoManager ) external; /** * Set trusted addresses that are always allowed to submit and reveal. * Only ftso manager can call this method. */ function setTrustedAddresses(address[] memory _trustedAddresses) external; /** * Called from whitelister when new voter has been whitelisted. */ function voterWhitelisted(address _voter, uint256 _ftsoIndex) external; /** * Called from whitelister when one or more voters have been removed. */ function votersRemovedFromWhitelist(address[] memory _voters, uint256 _ftsoIndex) external; /** * Returns a list of trusted addresses that are always allowed to submit and reveal. */ function getTrustedAddresses() external view returns (address[] memory); } // File contracts/genesis/implementation/PriceSubmitter.sol // pragma solidity 0.7.6; /** * @title Price submitter * @notice A contract used to submit/reveal prices to multiple Flare Time Series Oracles in one transaction */ contract PriceSubmitter is IIPriceSubmitter, GovernedAtGenesis { string internal constant ERR_ARRAY_LENGTHS = "Array lengths do not match"; string internal constant ERR_NOT_WHITELISTED = "Not whitelisted"; string internal constant ERR_FTSO_MANAGER_ONLY = "FTSOManager only"; string internal constant ERR_WHITELISTER_ONLY = "Voter whitelister only"; IFtsoRegistryGenesis internal ftsoRegistry; address internal ftsoManager; address internal voterWhitelister; // Bit at index `i` corresponds to being whitelisted for vote on ftso at index `i` mapping(address => uint256) internal whitelistedFtsoBitmap; address[] internal trustedAddresses; // for checking addresses at submit/reveal mapping(address => bool) internal trustedAddressesMapping; modifier onlyFtsoManager { require(msg.sender == ftsoManager, ERR_FTSO_MANAGER_ONLY); _; } modifier onlyWhitelister { require(msg.sender == voterWhitelister, ERR_WHITELISTER_ONLY); _; } /** * @dev This constructor should contain no code as this contract is pre-loaded into the genesis block. * The super constructor is called for testing convenience. */ constructor() GovernedAtGenesis(address(0)) { /* empty block */ } /** * Sets ftso registry, voter whitelist and ftso manager contracts. * Only governance can call this method. * If replacing the registry or the whitelist and the old one is not empty, make sure to replicate the state, * otherwise internal whitelist bitmaps won't match. */ function setContractAddresses( IFtsoRegistryGenesis _ftsoRegistry, address _voterWhitelister, address _ftsoManager ) external override onlyGovernance { ftsoRegistry = _ftsoRegistry; voterWhitelister = _voterWhitelister; ftsoManager = _ftsoManager; } /** * Set trusted addresses that are always allowed to submit and reveal. * Only ftso manager can call this method. */ function setTrustedAddresses(address[] memory _trustedAddresses) external override onlyFtsoManager { // remove old addresses mapping uint256 len = trustedAddresses.length; for (uint256 i = 0; i < len; i++) { trustedAddressesMapping[trustedAddresses[i]] = false; } // set new addresses mapping len = _trustedAddresses.length; for (uint256 i = 0; i < len; i++) { trustedAddressesMapping[_trustedAddresses[i]] = true; } trustedAddresses = _trustedAddresses; } /** * Called from whitelister when new voter has been whitelisted. */ function voterWhitelisted(address _voter, uint256 _ftsoIndex) external override onlyWhitelister { whitelistedFtsoBitmap[_voter] |= 1 << _ftsoIndex; } /** * Called from whitelister when one or more voters have been removed. */ function votersRemovedFromWhitelist(address[] memory _removedVoters, uint256 _ftsoIndex) external override onlyWhitelister { for (uint256 i = 0; i < _removedVoters.length; i++) { whitelistedFtsoBitmap[_removedVoters[i]] &= ~(1 << _ftsoIndex); } } /** * @notice Submits price hashes for current epoch * @param _ftsoIndices List of ftso indices * @param _hashes List of hashed price and random number * @notice Emits PriceHashesSubmitted event */ function submitPriceHashes( uint256 _epochId, uint256[] memory _ftsoIndices, bytes32[] memory _hashes ) external override { // Submit the prices uint256 length = _ftsoIndices.length; require(length == _hashes.length, ERR_ARRAY_LENGTHS); IFtsoGenesis[] memory ftsos = ftsoRegistry.getFtsos(_ftsoIndices); uint256 allowedBitmask = whitelistedFtsoBitmap[msg.sender]; bool isTrustedAddress = false; for (uint256 i = 0; i < length; i++) { uint256 ind = _ftsoIndices[i]; if (allowedBitmask & (1 << ind) == 0) { if (!isTrustedAddress) { if (trustedAddressesMapping[msg.sender]) { isTrustedAddress = true; } else { revert(ERR_NOT_WHITELISTED); } } } ftsos[i].submitPriceHashSubmitter(msg.sender, _epochId, _hashes[i]); } emit PriceHashesSubmitted(msg.sender, _epochId, ftsos, _hashes, block.timestamp); } /** * @notice Reveals submitted prices during epoch reveal period * @param _epochId Id of the epoch in which the price hashes was submitted * @param _ftsoIndices List of ftso indices * @param _prices List of submitted prices in USD * @param _randoms List of submitted random numbers * @notice The hash of _price and _random must be equal to the submitted hash * @notice Emits PricesRevealed event */ function revealPrices( uint256 _epochId, uint256[] memory _ftsoIndices, uint256[] memory _prices, uint256[] memory _randoms ) external override { uint256 length = _ftsoIndices.length; require(length == _prices.length, ERR_ARRAY_LENGTHS); require(length == _randoms.length, ERR_ARRAY_LENGTHS); IFtsoGenesis[] memory ftsos = ftsoRegistry.getFtsos(_ftsoIndices); uint256 allowedBitmask = whitelistedFtsoBitmap[msg.sender]; bool isTrustedAddress = false; uint256 wNatVP = uint256(-1); for (uint256 i = 0; i < length; i++) { uint256 ind = _ftsoIndices[i]; if (allowedBitmask & (1 << ind) == 0) { if (!isTrustedAddress) { if (trustedAddressesMapping[msg.sender]) { isTrustedAddress = true; } else { revert(ERR_NOT_WHITELISTED); } } } // read native VP only once if (wNatVP == uint256(-1)) { wNatVP = ftsos[i].wNatVotePowerCached(msg.sender, _epochId); } // call reveal price on ftso ftsos[i].revealPriceSubmitter(msg.sender, _epochId, _prices[i], _randoms[i], wNatVP); } emit PricesRevealed(msg.sender, _epochId, ftsos, _prices, _randoms, block.timestamp); } /** * Returns bitmap of all ftso's for which `_voter` is allowed to submit prices/hashes. * If voter is allowed to vote for ftso at index (see *_FTSO_INDEX), the corrsponding * bit in the result will be 1. */ function voterWhitelistBitmap(address _voter) external view override returns (uint256) { return whitelistedFtsoBitmap[_voter]; } function getTrustedAddresses() external view override returns (address[] memory) { return trustedAddresses; } function getVoterWhitelister() external view override returns (address) { return voterWhitelister; } function getFtsoRegistry() external view override returns (IFtsoRegistryGenesis) { return ftsoRegistry; } function getFtsoManager() external view override returns (address) { return ftsoManager; } }
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"event","name":"GovernanceProposed","inputs":[{"type":"address","name":"proposedGovernance","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"GovernanceUpdated","inputs":[{"type":"address","name":"oldGovernance","internalType":"address","indexed":false},{"type":"address","name":"newGoveranance","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"PriceHashesSubmitted","inputs":[{"type":"address","name":"submitter","internalType":"address","indexed":true},{"type":"uint256","name":"epochId","internalType":"uint256","indexed":true},{"type":"address[]","name":"ftsos","internalType":"contract IFtsoGenesis[]","indexed":false},{"type":"bytes32[]","name":"hashes","internalType":"bytes32[]","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"PricesRevealed","inputs":[{"type":"address","name":"voter","internalType":"address","indexed":true},{"type":"uint256","name":"epochId","internalType":"uint256","indexed":true},{"type":"address[]","name":"ftsos","internalType":"contract IFtsoGenesis[]","indexed":false},{"type":"uint256[]","name":"prices","internalType":"uint256[]","indexed":false},{"type":"uint256[]","name":"randoms","internalType":"uint256[]","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"claimGovernance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getFtsoManager","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IFtsoRegistryGenesis"}],"name":"getFtsoRegistry","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getTrustedAddresses","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getVoterWhitelister","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"governance","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[],"name":"initialise","inputs":[{"type":"address","name":"_governance","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"initialiseFixedAddress","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"proposeGovernance","inputs":[{"type":"address","name":"_governance","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"proposedGovernance","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"revealPrices","inputs":[{"type":"uint256","name":"_epochId","internalType":"uint256"},{"type":"uint256[]","name":"_ftsoIndices","internalType":"uint256[]"},{"type":"uint256[]","name":"_prices","internalType":"uint256[]"},{"type":"uint256[]","name":"_randoms","internalType":"uint256[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setContractAddresses","inputs":[{"type":"address","name":"_ftsoRegistry","internalType":"contract IFtsoRegistryGenesis"},{"type":"address","name":"_voterWhitelister","internalType":"address"},{"type":"address","name":"_ftsoManager","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setTrustedAddresses","inputs":[{"type":"address[]","name":"_trustedAddresses","internalType":"address[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"submitPriceHashes","inputs":[{"type":"uint256","name":"_epochId","internalType":"uint256"},{"type":"uint256[]","name":"_ftsoIndices","internalType":"uint256[]"},{"type":"bytes32[]","name":"_hashes","internalType":"bytes32[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferGovernance","inputs":[{"type":"address","name":"_governance","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"voterWhitelistBitmap","inputs":[{"type":"address","name":"_voter","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"voterWhitelisted","inputs":[{"type":"address","name":"_voter","internalType":"address"},{"type":"uint256","name":"_ftsoIndex","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"votersRemovedFromWhitelist","inputs":[{"type":"address[]","name":"_removedVoters","internalType":"address[]"},{"type":"uint256","name":"_ftsoIndex","internalType":"uint256"}]}]
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106101165760003560e01c80639d6a890f116100a2578063c373a08e11610071578063c373a08e1461051b578063c5adc53914610541578063c9f960eb1461066b578063d38bfff414610673578063ffacb84e1461069957610116565b80639d6a890f146104205780639d986f91146104465780639ec2b58114610472578063b39c68581461051357610116565b806371e1fad9116100e957806371e1fad9146102fd57806376794efb146103055780637ac420ad146103a85780638ab63380146103e05780638c9d28b61461041857610116565b80635aa6e6751461011b5780635d36b1901461013f57806360848b441461014957806360f7ac97146102f5575b600080fd5b6101236106f1565b604080516001600160a01b039092168252519081900360200190f35b610147610700565b005b6101476004803603608081101561015f57600080fd5b81359190810190604081016020820135600160201b81111561018057600080fd5b82018360208201111561019257600080fd5b803590602001918460208302840111600160201b831117156101b357600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561020257600080fd5b82018360208201111561021457600080fd5b803590602001918460208302840111600160201b8311171561023557600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561028457600080fd5b82018360208201111561029657600080fd5b803590602001918460208302840111600160201b831117156102b757600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506107c2945050505050565b610123610dbe565b610123610dcd565b6101476004803603604081101561031b57600080fd5b810190602081018135600160201b81111561033557600080fd5b82018360208201111561034757600080fd5b803590602001918460208302840111600160201b8311171561036857600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295505091359250610ddc915050565b6103ce600480360360208110156103be57600080fd5b50356001600160a01b0316610ebd565b60408051918252519081900360200190f35b610147600480360360608110156103f657600080fd5b506001600160a01b038135811691602081013582169160409091013516610ed8565b610123610f68565b6101476004803603602081101561043657600080fd5b50356001600160a01b0316610f77565b6101476004803603604081101561045c57600080fd5b506001600160a01b038135169060200135610f79565b6101476004803603602081101561048857600080fd5b810190602081018135600160201b8111156104a257600080fd5b8201836020820111156104b457600080fd5b803590602001918460208302840111600160201b831117156104d557600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611029945050505050565b610123611177565b6101476004803603602081101561053157600080fd5b50356001600160a01b0316611186565b6101476004803603606081101561055757600080fd5b81359190810190604081016020820135600160201b81111561057857600080fd5b82018360208201111561058a57600080fd5b803590602001918460208302840111600160201b831117156105ab57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b8111156105fa57600080fd5b82018360208201111561060c57600080fd5b803590602001918460208302840111600160201b8311171561062d57600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092955061122b945050505050565b6101236115e6565b6101476004803603602081101561068957600080fd5b50356001600160a01b031661160b565b6106a16116cd565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156106dd5781810151838201526020016106c5565b505050509050019250505060405180910390f35b6000546001600160a01b031681565b6001546001600160a01b0316331461074f576040805162461bcd60e51b815260206004820152600d60248201526c1b9bdd0818db185a5b585a5b9d609a1b604482015290519081900360640190fd5b600054600154604080516001600160a01b03938416815292909116602083015280517f434a2db650703b36c824e745330d6397cdaa9ee2cc891a4938ae853e1c50b68d9281900390910190a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b8251825160408051808201909152601a815279082e4e4c2f240d8cadccee8d0e640c8de40dcdee840dac2e8c6d60331b60208201529082146108825760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561084757818101518382015260200161082f565b50505050905090810190601f1680156108745780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50815181146040518060400160405280601a815260200179082e4e4c2f240d8cadccee8d0e640c8de40dcdee840dac2e8c6d60331b815250906109065760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561084757818101518382015260200161082f565b506002546040516313968ea760e31b81526020600482018181528751602484015287516000946001600160a01b031693639cb47538938a939283926044019180860191028083838b5b8381101561096757818101518382015260200161094f565b505050509050019250505060006040518083038186803b15801561098a57600080fd5b505afa15801561099e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156109c757600080fd5b8101908080516040519392919084600160201b8211156109e657600080fd5b9083019060208201858111156109fb57600080fd5b82518660208202830111600160201b82111715610a1757600080fd5b82525081516020918201928201910280838360005b83811015610a44578181015183820152602001610a2c565b5050505091909101604090815233600090815260056020529081205495965093506000199250839150505b85811015610c9e576000898281518110610a8557fe5b60200260200101519050806001901b851660001415610b2e5783610b2e573360009081526007602052604090205460ff1615610ac45760019350610b2e565b604080518082018252600f81526e139bdd081dda1a5d195b1a5cdd1959608a1b6020808301918252925162461bcd60e51b8152600481019384528251602482015282519293928392604490920191908083836000831561084757818101518382015260200161082f565b600019831415610bd157858281518110610b4457fe5b60200260200101516001600160a01b031663f72cab28338d6040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015610ba257600080fd5b505af1158015610bb6573d6000803e3d6000fd5b505050506040513d6020811015610bcc57600080fd5b505192505b858281518110610bdd57fe5b60200260200101516001600160a01b03166355f7b69b338d8c8681518110610c0157fe5b60200260200101518c8781518110610c1557fe5b6020026020010151886040518663ffffffff1660e01b815260040180866001600160a01b0316815260200185815260200184815260200183815260200182815260200195505050505050600060405180830381600087803b158015610c7957600080fd5b505af1158015610c8d573d6000803e3d6000fd5b505060019093019250610a6f915050565b5088336001600160a01b03167fa32444a31df2f9a116229eec3193d223a6bad89f7670ff17b8e5c7014a377da1868a8a4260405180806020018060200180602001858152602001848103845288818151815260200191508051906020019060200280838360005b83811015610d1d578181015183820152602001610d05565b50505050905001848103835287818151815260200191508051906020019060200280838360005b83811015610d5c578181015183820152602001610d44565b50505050905001848103825286818151815260200191508051906020019060200280838360005b83811015610d9b578181015183820152602001610d83565b5050505090500197505050505050505060405180910390a3505050505050505050565b6001546001600160a01b031681565b6004546001600160a01b031690565b600454604080518082019091526016815275566f7465722077686974656c6973746572206f6e6c7960501b6020820152906001600160a01b03163314610e635760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561084757818101518382015260200161082f565b5060005b8251811015610eb857816001901b1960056000858481518110610e8657fe5b6020908102919091018101516001600160a01b0316825281019190915260400160002080549091169055600101610e67565b505050565b6001600160a01b031660009081526005602052604090205490565b6000546001600160a01b03163314610f29576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920676f7665726e616e636560881b604482015290519081900360640190fd5b600280546001600160a01b039485166001600160a01b031991821617909155600480549385169382169390931790925560038054919093169116179055565b6002546001600160a01b031690565bfe5b600454604080518082019091526016815275566f7465722077686974656c6973746572206f6e6c7960501b6020820152906001600160a01b031633146110005760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561084757818101518382015260200161082f565b506001600160a01b0390911660009081526005602052604090208054600190921b919091179055565b60035460408051808201909152601081526f4654534f4d616e61676572206f6e6c7960801b6020820152906001600160a01b031633146110aa5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561084757818101518382015260200161082f565b5060065460005b8181101561110857600060076000600684815481106110cc57fe5b6000918252602080832091909101546001600160a01b031683528201929092526040019020805460ff19169115159190911790556001016110b1565b5050805160005b818110156111635760016007600085848151811061112957fe5b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905560010161110f565b508151610eb8906006906020850190611809565b6003546001600160a01b031690565b6000546001600160a01b031633146111d7576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920676f7665726e616e636560881b604482015290519081900360640190fd5b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f1f95fb40be3a947982072902a887b521248d1d8931a39eb38f84f4d6fd758b699181900360200190a150565b8151815160408051808201909152601a815279082e4e4c2f240d8cadccee8d0e640c8de40dcdee840dac2e8c6d60331b60208201529082146112ae5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561084757818101518382015260200161082f565b506002546040516313968ea760e31b81526020600482018181528651602484015286516000946001600160a01b031693639cb475389389939283926044019180860191028083838b5b8381101561130f5781810151838201526020016112f7565b505050509050019250505060006040518083038186803b15801561133257600080fd5b505afa158015611346573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561136f57600080fd5b8101908080516040519392919084600160201b82111561138e57600080fd5b9083019060208201858111156113a357600080fd5b82518660208202830111600160201b821117156113bf57600080fd5b82525081516020918201928201910280838360005b838110156113ec5781810151838201526020016113d4565b50505050919091016040908152336000908152600560205290812054959650935083925050505b8481101561150e57600087828151811061142957fe5b60200260200101519050806001901b8416600014156114645782611464573360009081526007602052604090205460ff1615610ac457600192505b84828151811061147057fe5b60200260200101516001600160a01b03166327bd2ad5338b8a868151811061149457fe5b60200260200101516040518463ffffffff1660e01b815260040180846001600160a01b031681526020018381526020018281526020019350505050600060405180830381600087803b1580156114e957600080fd5b505af11580156114fd573d6000803e3d6000fd5b505060019093019250611413915050565b5086336001600160a01b03167f90c022ade239639b1f8c4ebb8a76df5e03a7129df46cf9bcdae3c1450ea35434858842604051808060200180602001848152602001838103835286818151815260200191508051906020019060200280838360005b83811015611588578181015183820152602001611570565b50505050905001838103825285818151815260200191508051906020019060200280838360005b838110156115c75781810151838201526020016115af565b505050509050019550505050505060405180910390a350505050505050565b600073fffec6c83c8bf5c3f4ae0ccf8c45ce20e4560bd76116068161172f565b905090565b6000546001600160a01b0316331461165c576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920676f7665726e616e636560881b604482015290519081900360640190fd5b600054604080516001600160a01b039283168152918316602083015280517f434a2db650703b36c824e745330d6397cdaa9ee2cc891a4938ae853e1c50b68d9281900390910190a1600080546001600160a01b039092166001600160a01b0319928316179055600180549091169055565b6060600680548060200260200160405190810160405280929190818152602001828054801561172557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611707575b5050505050905090565b600154600160a01b900460ff1615611785576040805162461bcd60e51b8152602060048201526014602482015273696e697469616c6973656420213d2066616c736560601b604482015290519081900360640190fd5b6001805460ff60a01b1916600160a01b179055600054604080516001600160a01b039283168152918316602083015280517f434a2db650703b36c824e745330d6397cdaa9ee2cc891a4938ae853e1c50b68d9281900390910190a1600080546001600160a01b039092166001600160a01b0319928316179055600180549091169055565b82805482825590600052602060002090810192821561185e579160200282015b8281111561185e57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190611829565b5061186a92915061186e565b5090565b5b8082111561186a576000815560010161186f56fea2646970667358221220c1d73dd5d713527b4b18f6ca6d3d915fe356fa5425b5776172fa3bf91a5476e564736f6c63430007060033