diff --git a/CHANGELOG.md b/CHANGELOG.md index 4243a946..5e5fb8d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## Unreleased +## [4.15.0] - 2024-10-30 +### Changed +- update list of validators in Bank + ## [4.14.0] - 2024-07-16 ### Added - `UniswapV3FetcherHelper` diff --git a/deployments/arbitrum_production/ForeignChain.json b/deployments/arbitrum_production/ForeignChain.json index 5b8edd87..b9cd1b6d 100644 --- a/deployments/arbitrum_production/ForeignChain.json +++ b/deployments/arbitrum_production/ForeignChain.json @@ -1,5 +1,5 @@ { - "address": "0xa42cFc6a5bAB64Bd7dF5c96FFB40B86d50D0d65C", + "address": "0x3f7D481DC7156a79a49b57Cf5466dBA9FfB0e8Ca", "abi": [ { "inputs": [ @@ -1051,47 +1051,47 @@ "type": "function" } ], - "transactionHash": "0xf4acb7ff82189769c530f5df888135ab1c9341d87953ce2f8a68da545b8adc79", + "transactionHash": "0x1c42a840ddd00e41d60134784e7ea56c00cd326e41e9f389edc9725fc394470f", "receipt": { "to": null, "from": "0xA6e4fFa19B213AbeA258ae72e8e1a209B9E543e7", - "contractAddress": "0xa42cFc6a5bAB64Bd7dF5c96FFB40B86d50D0d65C", - "transactionIndex": 2, - "gasUsed": "32420738", - "logsBloom": "0x00000000000000000000000000000000000000000000000000800400400000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000020400000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000400010000000000000400000000000000000000000000000000000020000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x652692b7c854db15ebffa6e9793ebd1e52b2179405bb99bd9bb9bafd191d78d6", - "transactionHash": "0xf4acb7ff82189769c530f5df888135ab1c9341d87953ce2f8a68da545b8adc79", + "contractAddress": "0x3f7D481DC7156a79a49b57Cf5466dBA9FfB0e8Ca", + "transactionIndex": 11, + "gasUsed": "8754607", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000400000000000000000000000000000000000000000000000000000000000000000000000000800040000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000020400000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000010000000000000400000000000000000000000000000000000020000000000000000000000020000000000000000000000100000000000000000000000000000000000000000000", + "blockHash": "0x35b2dc4d58d06af12df16993c066e0afbfc9049d2b4dc9edc383bb4ff69459b4", + "transactionHash": "0x1c42a840ddd00e41d60134784e7ea56c00cd326e41e9f389edc9725fc394470f", "logs": [ { - "transactionIndex": 2, - "blockNumber": 147998670, - "transactionHash": "0xf4acb7ff82189769c530f5df888135ab1c9341d87953ce2f8a68da545b8adc79", - "address": "0xa42cFc6a5bAB64Bd7dF5c96FFB40B86d50D0d65C", + "transactionIndex": 11, + "blockNumber": 269196231, + "transactionHash": "0x1c42a840ddd00e41d60134784e7ea56c00cd326e41e9f389edc9725fc394470f", + "address": "0x3f7D481DC7156a79a49b57Cf5466dBA9FfB0e8Ca", "topics": [ "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x000000000000000000000000a6e4ffa19b213abea258ae72e8e1a209b9e543e7" ], "data": "0x", - "logIndex": 16, - "blockHash": "0x652692b7c854db15ebffa6e9793ebd1e52b2179405bb99bd9bb9bafd191d78d6" + "logIndex": 64, + "blockHash": "0x35b2dc4d58d06af12df16993c066e0afbfc9049d2b4dc9edc383bb4ff69459b4" }, { - "transactionIndex": 2, - "blockNumber": 147998670, - "transactionHash": "0xf4acb7ff82189769c530f5df888135ab1c9341d87953ce2f8a68da545b8adc79", - "address": "0xa42cFc6a5bAB64Bd7dF5c96FFB40B86d50D0d65C", + "transactionIndex": 11, + "blockNumber": 269196231, + "transactionHash": "0x1c42a840ddd00e41d60134784e7ea56c00cd326e41e9f389edc9725fc394470f", + "address": "0x3f7D481DC7156a79a49b57Cf5466dBA9FfB0e8Ca", "topics": [ "0x02ff77a0f68d11f7efb906f331b2dda82916de8ba9c37dda2a95817936a530ec", "0x000000000000000000000000a6e4ffa19b213abea258ae72e8e1a209b9e543e7" ], "data": "0x0000000000000000000000000000000000000000000000000000000000005460", - "logIndex": 17, - "blockHash": "0x652692b7c854db15ebffa6e9793ebd1e52b2179405bb99bd9bb9bafd191d78d6" + "logIndex": 65, + "blockHash": "0x35b2dc4d58d06af12df16993c066e0afbfc9049d2b4dc9edc383bb4ff69459b4" } ], - "blockNumber": 147998670, - "cumulativeGasUsed": "36669077", + "blockNumber": 269196231, + "cumulativeGasUsed": "12606275", "status": 1, "byzantium": true }, @@ -1102,7 +1102,7 @@ false ], "numDeployments": 1, - "solcInputHash": "4db3e1d3dd51dbe508dc0a6a04352df6", + "solcInputHash": "dc68422c0ad35a4fe46d461b096b9383", "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"_contractRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"_padding\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"_requiredSignatures\",\"type\":\"uint16\"},{\"internalType\":\"bool\",\"name\":\"_allowForMixedType\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyDeprecated\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArraysDataDoNotMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BlockSubmittedToFastOrDataToOld\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractNotReady\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FCDOverflow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContractType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoChangeToState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotEnoughSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotSupported\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyOwnerOrRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfOrder\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnregisterFirst\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"deprecator\",\"type\":\"address\"}],\"name\":\"LogDeprecation\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"blockId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"staked\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"power\",\"type\":\"uint256\"}],\"name\":\"LogMint\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"executor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"timePadding\",\"type\":\"uint32\"}],\"name\":\"LogPadding\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"blockId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"vote\",\"type\":\"uint256\"}],\"name\":\"LogVoter\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ETH_PREFIX\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_blockId\",\"type\":\"uint256\"}],\"name\":\"blocks\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"dataTimestamp\",\"type\":\"uint32\"}],\"internalType\":\"struct BaseChain.Block\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blocksCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blocksCountOffset\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_offset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_items\",\"type\":\"uint256\"}],\"name\":\"bytesToBytes32Array\",\"outputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"contractRegistry\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deprecate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"fcds\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"dataTimestamp\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockId\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"getBlockIdAtTimestamp\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_blockId\",\"type\":\"uint32\"}],\"name\":\"getBlockRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_blockId\",\"type\":\"uint32\"}],\"name\":\"getBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConsensusData\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"blocksCountOffset\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"sequence\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"lastTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"padding\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"deprecated\",\"type\":\"bool\"}],\"internalType\":\"struct BaseChain.ConsensusData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getCurrentIntValue\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"value\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getCurrentValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_keys\",\"type\":\"bytes32[]\"}],\"name\":\"getCurrentValues\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"uint32[]\",\"name\":\"timestamps\",\"type\":\"uint32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestBlockId\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLeaderAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"getLeaderAddressAtTime\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"getLeaderIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNextLeaderAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStatus\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"timePadding\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"lastDataTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"lastId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"nextLeader\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"nextBlockId\",\"type\":\"uint32\"},{\"internalType\":\"address[]\",\"name\":\"validators\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"powers\",\"type\":\"uint256[]\"},{\"internalType\":\"string[]\",\"name\":\"locations\",\"type\":\"string[]\"},{\"internalType\":\"uint256\",\"name\":\"staked\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"minSignatures\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_key\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_value\",\"type\":\"bytes\"}],\"name\":\"hashLeaf\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isForeign\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastBlockId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_affidavit\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"_v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"_r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_s\",\"type\":\"bytes32\"}],\"name\":\"recoverSigner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"register\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"requiredSignatures\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"roots\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"_padding\",\"type\":\"uint16\"}],\"name\":\"setPadding\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stakingBank\",\"outputs\":[{\"internalType\":\"contract IStakingBank\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stakingBankContract\",\"outputs\":[{\"internalType\":\"contract IStakingBank\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_dataTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"_root\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"_keys\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_values\",\"type\":\"uint256[]\"},{\"internalType\":\"uint8[]\",\"name\":\"_v\",\"type\":\"uint8[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"_r\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"_s\",\"type\":\"bytes32[]\"}],\"name\":\"submit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"tokenContract\",\"outputs\":[{\"internalType\":\"contract ERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_proof\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"_root\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_leaf\",\"type\":\"bytes32\"}],\"name\":\"verifyProof\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_blockId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"_proof\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"_key\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_value\",\"type\":\"bytes\"}],\"name\":\"verifyProofForBlock\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"_blockIds\",\"type\":\"uint32[]\"},{\"internalType\":\"bytes\",\"name\":\"_proofs\",\"type\":\"bytes\"},{\"internalType\":\"uint256[]\",\"name\":\"_proofItemsCounter\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"_leaves\",\"type\":\"bytes32[]\"}],\"name\":\"verifyProofs\",\"outputs\":[{\"internalType\":\"bool[]\",\"name\":\"results\",\"type\":\"bool[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"contract for foreign chains\",\"kind\":\"dev\",\"methods\":{\"blocks(uint256)\":{\"params\":{\"_blockId\":\"ID of submitted block\"},\"returns\":{\"_0\":\"block data (root + timestamp)\"}},\"blocksCount()\":{\"details\":\"number of blocks (consensus rounds) saved in this contract\"},\"bytesToBytes32Array(bytes,uint256,uint256)\":{\"details\":\"this is helper method, that extracts one merkle proof from many hashed provided as bytes\",\"params\":{\"_data\":\"many hashes as bytes\",\"_items\":\"how many hashes to extract\",\"_offset\":\"this is starting point for extraction\"},\"returns\":{\"_0\":\"merkle proof (array of bytes32 hashes)\"}},\"constructor\":{\"params\":{\"_contractRegistry\":\"Registry address\",\"_padding\":\"required \\\"space\\\" between blocks in seconds\",\"_requiredSignatures\":\"number of required signatures for accepting consensus submission\"}},\"getBlockId()\":{\"returns\":{\"_0\":\"current block ID please note, that current ID is not the same as last ID, current means that once padding pass, ID will switch to next one and it will be pointing to empty submit until submit for that ID is done\"}},\"getBlockIdAtTimestamp(uint256)\":{\"details\":\"calculates block ID for provided timestamp this function does not works for past timestamps\",\"params\":{\"_timestamp\":\"current or future timestamp\"},\"returns\":{\"_0\":\"block ID for provided timestamp\"}},\"getBlockRoot(uint32)\":{\"params\":{\"_blockId\":\"consensus ID\"},\"returns\":{\"_0\":\"root for provided consensus ID\"}},\"getBlockTimestamp(uint32)\":{\"params\":{\"_blockId\":\"consensus ID\"},\"returns\":{\"_0\":\"timestamp for provided consensus ID\"}},\"getConsensusData()\":{\"details\":\"getter for `_consensusData`\"},\"getCurrentIntValue(bytes32)\":{\"details\":\"getter for single FCD value in case its type is `int`\",\"params\":{\"_key\":\"FCD key\"},\"returns\":{\"timestamp\":\"FCD timestamp\",\"value\":\"FCD value\"}},\"getCurrentValue(bytes32)\":{\"details\":\"getter for single FCD value\",\"params\":{\"_key\":\"FCD key\"},\"returns\":{\"timestamp\":\"FCD timestamp\",\"value\":\"FCD value\"}},\"getCurrentValues(bytes32[])\":{\"details\":\"batch getter for FCDs\",\"params\":{\"_keys\":\"FCDs keys to fetch\"},\"returns\":{\"timestamps\":\"array of FCDs timestamps\",\"values\":\"array of FCDs values\"}},\"getLatestBlockId()\":{\"returns\":{\"_0\":\"last submitted block ID, please note, that on deployment, when there is no submission for this contract block for last ID will be available in previous contract\"}},\"getLeaderAddress()\":{\"returns\":{\"_0\":\"address of current leader\"}},\"getName()\":{\"returns\":{\"_0\":\"contract name as bytes32\"}},\"getNextLeaderAddress()\":{\"returns\":{\"_0\":\"address of leader for next second\"}},\"getStatus()\":{\"details\":\"helper method that returns all important data about current state of contract\",\"returns\":{\"blockNumber\":\"`block.number`\",\"lastDataTimestamp\":\"timestamp for last submitted consensus\",\"lastId\":\"ID of last submitted consensus\",\"locations\":\"array will be always empty\",\"minSignatures\":\"`this.requiredSignatures`\",\"nextBlockId\":\"block ID for `block.timestamp + padding`\",\"nextLeader\":\"will be always address(0)\",\"powers\":\"array will be always empty\",\"staked\":\"total UMB staked by validators\",\"timePadding\":\"`this.padding`\",\"validators\":\"array will be always empty\"}},\"hashLeaf(bytes,bytes)\":{\"details\":\"creates leaf hash, that has is used in merkle tree\",\"params\":{\"_key\":\"key under which we store the value\",\"_value\":\"value itself as bytes\"},\"returns\":{\"_0\":\"leaf hash\"}},\"isForeign()\":{\"returns\":{\"_0\":\"TRUE if contract is ForeignChain, FALSE otherwise\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"recoverSigner(bytes32,uint8,bytes32,bytes32)\":{\"params\":{\"_affidavit\":\"root and FCDs hashed together\",\"_r\":\"part of signature\",\"_s\":\"part of signature\",\"_v\":\"part of signature\"},\"returns\":{\"_0\":\"signer address\"}},\"register()\":{\"details\":\"this method will be called as a first method in registration process when old contract will be replaced when called, old contract address is still in registry\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setPadding(uint16)\":{\"details\":\"setter for `padding`\"},\"stakingBankContract()\":{\"details\":\"helper method for fetching StakingBank address\"},\"submit(uint32,bytes32,bytes32[],uint256[],uint8[],bytes32[],bytes32[])\":{\"details\":\"method for submitting consensus data\",\"params\":{\"_dataTimestamp\":\"consensus timestamp, this is time for all data in merkle tree including FCDs\",\"_keys\":\"FCDs keys\",\"_r\":\"array of `r` part of validators signatures\",\"_root\":\"merkle root\",\"_s\":\"array of `s` part of validators signatures\",\"_v\":\"array of `v` part of validators signatures\",\"_values\":\"FCDs values\"}},\"tokenContract()\":{\"details\":\"helper method for fetching UMB address\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"unregister()\":{\"details\":\"this method will be called as a last method in registration process when old contract will be replaced when called, new contract address is already in registry\"},\"verifyProof(bytes32[],bytes32,bytes32)\":{\"details\":\"verifies if the leaf is valid leaf for merkle tree\",\"params\":{\"_leaf\":\"leaf hash\",\"_proof\":\"merkle proof for merkle tree\",\"_root\":\"merkle root\"},\"returns\":{\"_0\":\"TRUE if `_leaf` is valid, FALSE otherwise\"}},\"verifyProofForBlock(uint256,bytes32[],bytes,bytes)\":{\"details\":\"verifies, if provided key-value pair was part of consensus\",\"params\":{\"_blockId\":\"consensus ID for which we doing a check\",\"_key\":\"pair key\",\"_proof\":\"merkle proof for pair\",\"_value\":\"pair value\"},\"returns\":{\"_0\":\"TRUE if key-value par was part of consensus, FALSE otherwise\"}},\"verifyProofs(uint32[],bytes,uint256[],bytes32[])\":{\"details\":\"batch method for data verification\",\"params\":{\"_blockIds\":\"consensus IDs for which we doing a checks\",\"_leaves\":\"array of merkle leaves\",\"_proofItemsCounter\":\"array of counters, each counter tells how many hashes proof for each leaf has\",\"_proofs\":\"merkle proofs for all pair, sequence of hashes provided as bytes\"},\"returns\":{\"results\":\"array of verification results, TRUE if leaf is part of consensus, FALSE otherwise\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"deprecate()\":{\"notice\":\"it allows to deprecate contract manually Only new Registry calls `unregister()` where we set deprecated to true In old Registries we don't have this feature, so in order to safely redeploy new Chain we will have to first deprecate current contract manually, then register new contract\"},\"getStatus()\":{\"notice\":\"this method is made to be compatible with MasterChain, but it does not return full data eg validators data will be missing.\"},\"register()\":{\"notice\":\"if this method needs to be called manually (not from Registry) it is important to do it as part of tx batch eg using multisig, we should prepare set of transactions and confirm them all at once\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/ForeignChain.sol\":\"ForeignChain\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":0},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0x24e0364e503a9bbde94c715d26573a76f14cd2a202d45f96f52134ab806b67b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\\n * instead returning `false` on failure. This behavior is nonetheless\\n * conventional and does not conflict with the expectations of ERC20\\n * applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * The default value of {decimals} is 18. To select a different value for\\n * {decimals} you should overload it.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n * overridden;\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\\n * `transferFrom`. This is semantically equivalent to an infinite approval.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * NOTE: Does not update the allowance if the current allowance\\n * is the maximum `uint256`.\\n *\\n * Requirements:\\n *\\n * - `from` and `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) public virtual override returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, amount);\\n _transfer(from, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, allowance(owner, spender) + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n uint256 currentAllowance = allowance(owner, spender);\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n */\\n function _transfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {\\n require(from != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(to != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, amount);\\n\\n uint256 fromBalance = _balances[from];\\n require(fromBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[from] = fromBalance - amount;\\n }\\n _balances[to] += amount;\\n\\n emit Transfer(from, to, amount);\\n\\n _afterTokenTransfer(from, to, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n _balances[account] += amount;\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n }\\n _totalSupply -= amount;\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(\\n address owner,\\n address spender,\\n uint256 amount\\n ) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\\n *\\n * Does not update the allowance amount in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Might emit an {Approval} event.\\n */\\n function _spendAllowance(\\n address owner,\\n address spender,\\n uint256 amount\\n ) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance != type(uint256).max) {\\n require(currentAllowance >= amount, \\\"ERC20: insufficient allowance\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - amount);\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {}\\n}\\n\",\"keccak256\":\"0xe0c8b625a79bac0fe80f17cfb521e072805cc9cef1c96a5caf45b264e74812fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/cryptography/MerkleProof.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev These functions deal with verification of Merkle Trees proofs.\\n *\\n * The proofs can be generated using the JavaScript library\\n * https://github.com/miguelmota/merkletreejs[merkletreejs].\\n * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.\\n *\\n * See `test/utils/cryptography/MerkleProof.test.js` for some examples.\\n *\\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\\n * hashing, or use a hash function other than keccak256 for hashing leaves.\\n * This is because the concatenation of a sorted pair of internal nodes in\\n * the merkle tree could be reinterpreted as a leaf value.\\n */\\nlibrary MerkleProof {\\n /**\\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\\n * defined by `root`. For this, a `proof` must be provided, containing\\n * sibling hashes on the branch from the leaf to the root of the tree. Each\\n * pair of leaves and each pair of pre-images are assumed to be sorted.\\n */\\n function verify(\\n bytes32[] memory proof,\\n bytes32 root,\\n bytes32 leaf\\n ) internal pure returns (bool) {\\n return processProof(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\\n * hash matches the root of the tree. When processing the proof, the pairs\\n * of leafs & pre-images are assumed to be sorted.\\n *\\n * _Available since v4.4._\\n */\\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n bytes32 proofElement = proof[i];\\n if (computedHash <= proofElement) {\\n // Hash(current computed hash + current element of the proof)\\n computedHash = _efficientHash(computedHash, proofElement);\\n } else {\\n // Hash(current element of the proof + current computed hash)\\n computedHash = _efficientHash(proofElement, computedHash);\\n }\\n }\\n return computedHash;\\n }\\n\\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\\n assembly {\\n mstore(0x00, a)\\n mstore(0x20, b)\\n value := keccak256(0x00, 0x40)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaaa504ac17eb0298dcdf5733ce24021b4914f035b97f4400b92827341d3facb3\",\"license\":\"MIT\"},\"@umb-network/toolbox/dist/contracts/lib/ValueDecoder.sol\":{\"content\":\"//SPDX-License-Identifier: Unlicensed\\npragma solidity >=0.6.8;\\n\\nlibrary ValueDecoder {\\n function toUint(bytes memory _bytes) internal pure returns (uint256 value) {\\n assembly {\\n value := mload(add(_bytes, 32))\\n }\\n }\\n\\n function toUint(bytes32 _bytes) internal pure returns (uint256 value) {\\n assembly {\\n value := _bytes\\n }\\n }\\n\\n function toInt(uint224 u) internal pure returns (int256) {\\n int224 i;\\n uint224 max = type(uint224).max;\\n\\n if (u <= (max - 1) / 2) { // positive values\\n assembly {\\n i := add(u, 0)\\n }\\n\\n return i;\\n } else { // negative values\\n assembly {\\n i := sub(sub(u, max), 1)\\n }\\n }\\n\\n return i;\\n }\\n}\\n\\n\",\"keccak256\":\"0x4c27669880111dd724930e6e2cb0baefdb3a8b7b2d6ffc0ec5c5534bc678a852\",\"license\":\"Unlicensed\"},\"contracts/BaseChain.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\\\";\\nimport \\\"@umb-network/toolbox/dist/contracts/lib/ValueDecoder.sol\\\";\\n\\nimport \\\"./interfaces/IBaseChainV1.sol\\\";\\nimport \\\"./interfaces/IStakingBank.sol\\\";\\nimport \\\"./extensions/Registrable.sol\\\";\\nimport \\\"./Registry.sol\\\";\\n\\nabstract contract BaseChain is Registrable, Ownable {\\n using ValueDecoder for bytes;\\n using ValueDecoder for uint224;\\n using MerkleProof for bytes32[];\\n\\n /// @param root merkle root for consensus\\n /// @param dataTimestamp consensus timestamp\\n struct Block {\\n bytes32 root;\\n uint32 dataTimestamp;\\n }\\n\\n /// @param value FCD value\\n /// @param dataTimestamp FCD timestamp\\n struct FirstClassData {\\n uint224 value;\\n uint32 dataTimestamp;\\n }\\n\\n /// @param blocksCountOffset number of all blocks that were generated before switching to this contract\\n /// @param sequence is a total number of blocks (consensus rounds) including previous contracts\\n /// @param lastTimestamp is a timestamp of last submitted block\\n /// @param padding number of seconds that need to pass before new submit will be possible\\n /// @param deprecated flag that changes to TRUE on `unregister`, when TRUE submissions are not longer available\\n struct ConsensusData {\\n uint32 blocksCountOffset;\\n uint32 sequence;\\n uint32 lastTimestamp;\\n uint32 padding;\\n bool deprecated;\\n }\\n\\n uint256 constant public VERSION = 2;\\n\\n bool internal immutable _ALLOW_FOR_MIXED_TYPE; // solhint-disable-line var-name-mixedcase\\n\\n bytes4 constant private _VERSION_SELECTOR = bytes4(keccak256(\\\"VERSION()\\\"));\\n\\n /// @dev minimal number of signatures required for accepting submission (PoA)\\n uint16 internal immutable _REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\\n\\n ConsensusData internal _consensusData;\\n\\n bytes constant public ETH_PREFIX = \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\";\\n\\n /// @dev block id (consensus ID) => root\\n /// consensus ID is at the same time consensus timestamp\\n mapping(uint256 => bytes32) public roots;\\n\\n /// @dev FCD key => FCD data\\n mapping(bytes32 => FirstClassData) public fcds;\\n\\n event LogDeprecation(address indexed deprecator);\\n event LogPadding(address indexed executor, uint32 timePadding);\\n\\n error ArraysDataDoNotMatch();\\n error AlreadyDeprecated();\\n error AlreadyRegistered();\\n error BlockSubmittedToFastOrDataToOld();\\n error ContractNotReady();\\n error FCDOverflow();\\n error InvalidContractType();\\n error NoChangeToState();\\n error OnlyOwnerOrRegistry();\\n error UnregisterFirst();\\n\\n modifier onlyOwnerOrRegistry () {\\n if (msg.sender != address(contractRegistry) && msg.sender != owner()) revert OnlyOwnerOrRegistry();\\n _;\\n }\\n\\n /// @param _contractRegistry Registry address\\n /// @param _padding required \\\"space\\\" between blocks in seconds\\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\\n constructor(\\n IRegistry _contractRegistry,\\n uint32 _padding,\\n uint16 _requiredSignatures,\\n bool _allowForMixedType\\n ) Registrable(_contractRegistry) {\\n _ALLOW_FOR_MIXED_TYPE = _allowForMixedType;\\n _REQUIRED_SIGNATURES = _requiredSignatures;\\n\\n _setPadding(_padding);\\n\\n BaseChain oldChain = BaseChain(_contractRegistry.getAddress(\\\"Chain\\\"));\\n\\n if (address(oldChain) == address(0)) {\\n // if this is first contract in sidechain, then we need to initialise lastTimestamp so submission\\n // can be possible\\n _consensusData.lastTimestamp = uint32(block.timestamp) - _padding - 1;\\n }\\n }\\n\\n /// @dev setter for `padding`\\n function setPadding(uint16 _padding) external {\\n _setPadding(_padding);\\n }\\n\\n /// @notice if this method needs to be called manually (not from Registry)\\n /// it is important to do it as part of tx batch\\n /// eg using multisig, we should prepare set of transactions and confirm them all at once\\n /// @inheritdoc Registrable\\n function register() external override onlyOwnerOrRegistry {\\n address oldChain = contractRegistry.getAddress(\\\"Chain\\\");\\n\\n // registration must be done before address in registry is replaced\\n if (oldChain == address(this)) revert AlreadyRegistered();\\n\\n if (oldChain == address(0x0)) {\\n return;\\n }\\n\\n _cloneLastDataFromPrevChain(oldChain);\\n }\\n\\n /// @inheritdoc Registrable\\n function unregister() external override onlyOwnerOrRegistry {\\n // in case we deprecated contract manually, we simply return\\n if (_consensusData.deprecated) return;\\n\\n address newChain = contractRegistry.getAddress(\\\"Chain\\\");\\n // unregistering must be done after address in registry is replaced\\n if (newChain == address(this)) revert UnregisterFirst();\\n\\n // TODO:\\n // I think we need to remove restriction for type (at least once)\\n // when we will switch to multichain architecture\\n\\n if (!_ALLOW_FOR_MIXED_TYPE) {\\n // can not be replaced with chain of different type\\n if (BaseChain(newChain).isForeign() != this.isForeign()) revert InvalidContractType();\\n }\\n\\n _consensusData.deprecated = true;\\n emit LogDeprecation(msg.sender);\\n }\\n\\n /// @notice it allows to deprecate contract manually\\n /// Only new Registry calls `unregister()` where we set deprecated to true\\n /// In old Registries we don't have this feature, so in order to safely redeploy new Chain\\n /// we will have to first deprecate current contract manually, then register new contract\\n function deprecate() external onlyOwnerOrRegistry {\\n if (_consensusData.deprecated) revert AlreadyDeprecated();\\n\\n _consensusData.deprecated = true;\\n emit LogDeprecation(msg.sender);\\n }\\n\\n /// @dev getter for `_consensusData`\\n function getConsensusData() external view returns (ConsensusData memory) {\\n return _consensusData;\\n }\\n\\n /// @dev number of blocks (consensus rounds) saved in this contract\\n function blocksCount() external view returns (uint256) {\\n return _consensusData.sequence - _consensusData.blocksCountOffset;\\n }\\n\\n function blocksCountOffset() external view returns (uint32) {\\n return _consensusData.blocksCountOffset;\\n }\\n\\n function lastBlockId() external view returns (uint256) {\\n return _consensusData.lastTimestamp;\\n }\\n\\n /// @return TRUE if contract is ForeignChain, FALSE otherwise\\n function isForeign() external pure virtual returns (bool);\\n\\n /// @inheritdoc Registrable\\n function getName() external pure override returns (bytes32) {\\n return \\\"Chain\\\";\\n }\\n\\n /// @param _affidavit root and FCDs hashed together\\n /// @param _v part of signature\\n /// @param _r part of signature\\n /// @param _s part of signature\\n /// @return signer address\\n function recoverSigner(bytes32 _affidavit, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _affidavit));\\n return ecrecover(hash, _v, _r, _s);\\n }\\n\\n /// @param _blockId ID of submitted block\\n /// @return block data (root + timestamp)\\n function blocks(uint256 _blockId) external view returns (Block memory) {\\n return Block(roots[_blockId], uint32(_blockId));\\n }\\n\\n /// @return current block ID\\n /// please note, that current ID is not the same as last ID, current means that once padding pass,\\n /// ID will switch to next one and it will be pointing to empty submit until submit for that ID is done\\n function getBlockId() external view returns (uint32) {\\n if (_consensusData.lastTimestamp == 0) return 0;\\n\\n return getBlockIdAtTimestamp(block.timestamp);\\n }\\n\\n function requiredSignatures() external view returns (uint16) {\\n return _REQUIRED_SIGNATURES;\\n }\\n\\n /// @dev calculates block ID for provided timestamp\\n /// this function does not works for past timestamps\\n /// @param _timestamp current or future timestamp\\n /// @return block ID for provided timestamp\\n function getBlockIdAtTimestamp(uint256 _timestamp) virtual public view returns (uint32) {\\n ConsensusData memory data = _consensusData;\\n\\n unchecked {\\n // we can't overflow because we adding two `uint32`\\n if (data.lastTimestamp + data.padding < _timestamp) {\\n return uint32(_timestamp);\\n }\\n }\\n\\n return data.lastTimestamp;\\n }\\n\\n /// @return last submitted block ID, please note, that on deployment, when there is no submission for this contract\\n /// block for last ID will be available in previous contract\\n function getLatestBlockId() virtual public view returns (uint32) {\\n return _consensusData.lastTimestamp;\\n }\\n\\n /// @dev verifies if the leaf is valid leaf for merkle tree\\n /// @param _proof merkle proof for merkle tree\\n /// @param _root merkle root\\n /// @param _leaf leaf hash\\n /// @return TRUE if `_leaf` is valid, FALSE otherwise\\n function verifyProof(bytes32[] memory _proof, bytes32 _root, bytes32 _leaf) public pure returns (bool) {\\n if (_root == bytes32(0)) {\\n return false;\\n }\\n\\n return _proof.verify(_root, _leaf);\\n }\\n\\n /// @dev creates leaf hash, that has is used in merkle tree\\n /// @param _key key under which we store the value\\n /// @param _value value itself as bytes\\n /// @return leaf hash\\n function hashLeaf(bytes memory _key, bytes memory _value) public pure returns (bytes32) {\\n return keccak256(abi.encodePacked(_key, _value));\\n }\\n\\n /// @dev verifies, if provided key-value pair was part of consensus\\n /// @param _blockId consensus ID for which we doing a check\\n /// @param _proof merkle proof for pair\\n /// @param _key pair key\\n /// @param _value pair value\\n /// @return TRUE if key-value par was part of consensus, FALSE otherwise\\n function verifyProofForBlock(\\n uint256 _blockId,\\n bytes32[] memory _proof,\\n bytes memory _key,\\n bytes memory _value\\n )\\n public\\n view\\n returns (bool)\\n {\\n return _proof.verify(roots[_blockId], keccak256(abi.encodePacked(_key, _value)));\\n }\\n\\n /// @dev this is helper method, that extracts one merkle proof from many hashed provided as bytes\\n /// @param _data many hashes as bytes\\n /// @param _offset this is starting point for extraction\\n /// @param _items how many hashes to extract\\n /// @return merkle proof (array of bytes32 hashes)\\n function bytesToBytes32Array(\\n bytes memory _data,\\n uint256 _offset,\\n uint256 _items\\n )\\n public\\n pure\\n returns (bytes32[] memory)\\n {\\n bytes32[] memory dataList = new bytes32[](_items);\\n\\n // we can unchecked because we working only with `i` and `_offset`\\n // in case of wrong `_offset` it will throw\\n unchecked {\\n for (uint256 i = 0; i < _items; i++) {\\n bytes32 temp;\\n uint256 idx = (i + 1 + _offset) * 32;\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n temp := mload(add(_data, idx))\\n }\\n\\n dataList[i] = temp;\\n }\\n }\\n\\n return (dataList);\\n }\\n\\n /// @dev batch method for data verification\\n /// @param _blockIds consensus IDs for which we doing a checks\\n /// @param _proofs merkle proofs for all pair, sequence of hashes provided as bytes\\n /// @param _proofItemsCounter array of counters, each counter tells how many hashes proof for each leaf has\\n /// @param _leaves array of merkle leaves\\n /// @return results array of verification results, TRUE if leaf is part of consensus, FALSE otherwise\\n function verifyProofs(\\n uint32[] memory _blockIds,\\n bytes memory _proofs,\\n uint256[] memory _proofItemsCounter,\\n bytes32[] memory _leaves\\n )\\n public\\n view\\n returns (bool[] memory results)\\n {\\n results = new bool[](_leaves.length);\\n uint256 offset = 0;\\n\\n for (uint256 i = 0; i < _leaves.length;) {\\n results[i] = bytesToBytes32Array(_proofs, offset, _proofItemsCounter[i]).verify(\\n roots[_blockIds[i]], _leaves[i]\\n );\\n\\n unchecked {\\n // we can uncheck because it will not overflow in a lifetime, and if someone provide invalid counter\\n // we verification will not be valid (or we throw because of invalid memory access)\\n offset += _proofItemsCounter[i];\\n // we can uncheck because `i` will not overflow in a lifetime\\n i++;\\n }\\n }\\n }\\n\\n /// @param _blockId consensus ID\\n /// @return root for provided consensus ID\\n function getBlockRoot(uint32 _blockId) external view returns (bytes32) {\\n return roots[_blockId];\\n }\\n\\n /// @param _blockId consensus ID\\n /// @return timestamp for provided consensus ID\\n function getBlockTimestamp(uint32 _blockId) external view returns (uint32) {\\n return roots[_blockId] == bytes32(0) ? 0 : _blockId;\\n }\\n\\n /// @dev batch getter for FCDs\\n /// @param _keys FCDs keys to fetch\\n /// @return values array of FCDs values\\n /// @return timestamps array of FCDs timestamps\\n function getCurrentValues(bytes32[] calldata _keys)\\n external\\n view\\n returns (uint256[] memory values, uint32[] memory timestamps)\\n {\\n timestamps = new uint32[](_keys.length);\\n values = new uint256[](_keys.length);\\n\\n for (uint i=0; i<_keys.length;) {\\n FirstClassData storage numericFCD = fcds[_keys[i]];\\n values[i] = uint256(numericFCD.value);\\n timestamps[i] = numericFCD.dataTimestamp;\\n\\n unchecked {\\n // we can uncheck because `i` will not overflow in a lifetime\\n i++;\\n }\\n }\\n }\\n\\n /// @dev getter for single FCD value\\n /// @param _key FCD key\\n /// @return value FCD value\\n /// @return timestamp FCD timestamp\\n function getCurrentValue(bytes32 _key) external view returns (uint256 value, uint256 timestamp) {\\n FirstClassData storage numericFCD = fcds[_key];\\n return (uint256(numericFCD.value), numericFCD.dataTimestamp);\\n }\\n\\n /// @dev getter for single FCD value in case its type is `int`\\n /// @param _key FCD key\\n /// @return value FCD value\\n /// @return timestamp FCD timestamp\\n function getCurrentIntValue(bytes32 _key) external view returns (int256 value, uint256 timestamp) {\\n FirstClassData storage numericFCD = fcds[_key];\\n return (numericFCD.value.toInt(), numericFCD.dataTimestamp);\\n }\\n\\n function _setPadding(uint32 _padding) internal onlyOwner {\\n if (_consensusData.padding == _padding) revert NoChangeToState();\\n\\n _consensusData.padding = _padding;\\n emit LogPadding(msg.sender, _padding);\\n }\\n\\n /// @dev we cloning last block time, because we will need reference point for next submissions\\n function _cloneLastDataFromPrevChain(address _prevChain) internal {\\n (bool success, bytes memory v) = _prevChain.staticcall(abi.encode(_VERSION_SELECTOR));\\n uint256 prevVersion = success ? abi.decode(v, (uint256)) : 1;\\n\\n if (prevVersion == 1) {\\n uint32 latestId = IBaseChainV1(address(_prevChain)).getLatestBlockId();\\n _consensusData.lastTimestamp = IBaseChainV1(address(_prevChain)).getBlockTimestamp(latestId);\\n\\n // +1 because getLatestBlockId subtracts 1\\n // +1 because it might be situation when tx is already in progress in old contract\\n // and old contract do not have deprecated flag\\n _consensusData.sequence = latestId + 2;\\n _consensusData.blocksCountOffset = latestId + 2;\\n } else { // VERSION 2\\n // with new Registry, we have register/unregister methods\\n // Chain will be deprecated, so there is no need to do \\\"+1\\\" as in old version\\n // TODO what with current Registries??\\n // we need a way to make it deprecated!\\n ConsensusData memory data = BaseChain(_prevChain).getConsensusData();\\n\\n _consensusData.sequence = data.sequence;\\n _consensusData.blocksCountOffset = data.sequence;\\n _consensusData.lastTimestamp = data.lastTimestamp;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcc7d655ad64f0a17cd71331260cf48828f0396e5e3b1428b6690c12f35a95db7\",\"license\":\"MIT\"},\"contracts/Chain.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./BaseChain.sol\\\";\\n\\ncontract Chain is BaseChain {\\n IStakingBank public immutable stakingBank;\\n\\n event LogMint(address indexed minter, uint256 blockId, uint256 staked, uint256 power);\\n event LogVoter(uint256 indexed blockId, address indexed voter, uint256 vote);\\n\\n error NotEnoughSignatures();\\n error SignaturesOutOfOrder();\\n\\n /// @param _contractRegistry Registry address\\n /// @param _padding required \\\"space\\\" between blocks in seconds\\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\\n /// @param _allowForMixedType we have two \\\"types\\\" of Chain: HomeChain and ForeignChain, when we redeploying\\n /// we don't want to mix up them, so we checking, if new Chain has the same type as current one.\\n /// However, when we will be switching from one homechain to another one, we have to allow for this mixing up.\\n /// This flag will tell contract, if this is the case.\\n constructor(\\n IRegistry _contractRegistry,\\n uint32 _padding,\\n uint16 _requiredSignatures,\\n bool _allowForMixedType\\n ) BaseChain(_contractRegistry, _padding, _requiredSignatures, _allowForMixedType) {\\n stakingBank = IStakingBank(_contractRegistry.requireAndGetAddress(\\\"StakingBank\\\"));\\n }\\n\\n /// @dev method for submitting consensus data\\n /// @param _dataTimestamp consensus timestamp, this is time for all data in merkle tree including FCDs\\n /// @param _root merkle root\\n /// @param _keys FCDs keys\\n /// @param _values FCDs values\\n /// @param _v array of `v` part of validators signatures\\n /// @param _r array of `r` part of validators signatures\\n /// @param _s array of `s` part of validators signatures\\n // solhint-disable-next-line function-max-lines, code-complexity\\n function submit(\\n uint32 _dataTimestamp,\\n bytes32 _root,\\n bytes32[] memory _keys,\\n uint256[] memory _values,\\n uint8[] memory _v,\\n bytes32[] memory _r,\\n bytes32[] memory _s\\n ) external {\\n // below two checks are only for pretty errors, so we can safe gas and allow for raw revert\\n // if (_keys.length != _values.length) revert ArraysDataDoNotMatch();\\n // if (_v.length != _r.length || _r.length != _s.length) revert ArraysDataDoNotMatch();\\n\\n _verifySubmitTimestampAndIncSequence(_dataTimestamp);\\n\\n // we can't expect minter will have exactly the same timestamp\\n // but for sure we can demand not to be off by a lot, that's why +3sec\\n // temporary remove this condition, because recently on ropsten we see cases when minter/node\\n // can be even 100sec behind\\n // require(_dataTimestamp <= block.timestamp + 3,\\n // string(abi.encodePacked(\\\"oh, so you can predict the future:\\\", _dataTimestamp - block.timestamp + 48)));\\n\\n bytes memory testimony = abi.encodePacked(_dataTimestamp, _root);\\n\\n for (uint256 i = 0; i < _keys.length;) {\\n if (uint224(_values[i]) != _values[i]) revert FCDOverflow();\\n\\n fcds[_keys[i]] = FirstClassData(uint224(_values[i]), _dataTimestamp);\\n testimony = abi.encodePacked(testimony, _keys[i], _values[i]);\\n\\n unchecked {\\n // we can't pass enough data to overflow\\n i++;\\n }\\n }\\n\\n uint256 signatures = 0;\\n uint256 power = 0;\\n //uint256 staked = stakingBank.totalSupply();\\n bytes32 affidavit = keccak256(testimony);\\n\\n address prevSigner = address(0x0);\\n\\n for (uint256 i; i < _v.length;) {\\n address signer = recoverSigner(affidavit, _v[i], _r[i], _s[i]);\\n uint256 balance = stakingBank.balanceOf(signer);\\n\\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\\n\\n prevSigner = signer;\\n\\n if (balance == 0) {\\n unchecked { i++; }\\n continue;\\n }\\n\\n signatures++;\\n emit LogVoter(uint256(_dataTimestamp), signer, balance);\\n\\n unchecked {\\n // we can't overflow because that means token overflowed\\n // and even if we do, we will get lower power\\n power += balance;\\n i++;\\n }\\n }\\n\\n if (signatures < _REQUIRED_SIGNATURES) revert NotEnoughSignatures();\\n\\n emit LogMint(msg.sender, _dataTimestamp, stakingBank.totalSupply(), power);\\n\\n // TODO remember to protect against flash loans when DPoS will be in place\\n // we turn on power once we have DPoS in action, we have PoA now\\n // require(power * 100 / staked >= 66, \\\"not enough power was gathered\\\");\\n\\n roots[_dataTimestamp] = _root;\\n _consensusData.lastTimestamp = _dataTimestamp;\\n }\\n\\n /// @inheritdoc BaseChain\\n function isForeign() external pure virtual override returns (bool) {\\n return false;\\n }\\n\\n /// @dev helper method that returns all important data about current state of contract\\n /// @return blockNumber `block.number`\\n /// @return timePadding `this.padding`\\n /// @return lastDataTimestamp timestamp for last submitted consensus\\n /// @return lastId ID of last submitted consensus\\n /// @return nextLeader leader for `block.timestamp + 1`\\n /// @return nextBlockId block ID for `block.timestamp + padding`\\n /// @return validators array of all validators addresses\\n /// @return powers array of all validators powers\\n /// @return locations array of all validators locations\\n /// @return staked total UMB staked by validators\\n /// @return minSignatures `this.requiredSignatures`\\n function getStatus() external view virtual returns(\\n uint256 blockNumber,\\n uint32 timePadding,\\n uint32 lastDataTimestamp,\\n uint32 lastId,\\n address nextLeader,\\n uint32 nextBlockId,\\n address[] memory validators,\\n uint256[] memory powers,\\n string[] memory locations,\\n uint256 staked,\\n uint16 minSignatures\\n ) {\\n ConsensusData memory data = _consensusData;\\n\\n blockNumber = block.number;\\n timePadding = data.padding;\\n lastId = data.lastTimestamp;\\n lastDataTimestamp = lastId;\\n minSignatures = _REQUIRED_SIGNATURES;\\n\\n staked = stakingBank.totalSupply();\\n uint256 numberOfValidators = stakingBank.getNumberOfValidators();\\n powers = new uint256[](numberOfValidators);\\n validators = new address[](numberOfValidators);\\n locations = new string[](numberOfValidators);\\n\\n for (uint256 i = 0; i < numberOfValidators;) {\\n validators[i] = stakingBank.addresses(i);\\n (, locations[i]) = stakingBank.validators(validators[i]);\\n powers[i] = stakingBank.balanceOf(validators[i]);\\n\\n unchecked {\\n // we will run out of gas before overflow happen\\n i++;\\n }\\n }\\n\\n unchecked {\\n // we will not overflow with timestamp in a lifetime\\n nextBlockId = lastId + data.padding + 1;\\n\\n nextLeader = numberOfValidators > 0\\n // we will not overflow with timestamp in a lifetime\\n ? validators[getLeaderIndex(numberOfValidators, block.timestamp + 1)]\\n : address(0);\\n }\\n }\\n\\n /// @return address of leader for next second\\n function getNextLeaderAddress() external view returns (address) {\\n return getLeaderAddressAtTime(block.timestamp + 1);\\n }\\n\\n /// @return address of current leader\\n function getLeaderAddress() external view returns (address) {\\n return getLeaderAddressAtTime(block.timestamp);\\n }\\n\\n /// @param _numberOfValidators total number of validators\\n /// @param _timestamp timestamp for which you want to calculate index\\n /// @return leader index, use it for StakingBank.addresses[index] to fetch leader address\\n function getLeaderIndex(uint256 _numberOfValidators, uint256 _timestamp) public view virtual returns (uint256) {\\n ConsensusData memory data = _consensusData;\\n\\n unchecked {\\n // we will not overflow on `timestamp` and `padding` in a life time\\n // timePadding + 1 => because padding is a space between blocks,\\n // so next round starts on first block after padding\\n // TODO will it work for off-chain??\\n uint256 validatorIndex = data.sequence + (_timestamp - data.lastTimestamp) / (data.padding + 1);\\n\\n return validatorIndex % _numberOfValidators;\\n }\\n }\\n\\n // @todo - properly handled non-enabled validators, newly added validators, and validators with low stake\\n /// @param _timestamp timestamp for which you want to calculate leader address\\n /// @return leader address for provider timestamp\\n function getLeaderAddressAtTime(uint256 _timestamp) public view virtual returns (address) {\\n uint256 numberOfValidators = stakingBank.getNumberOfValidators();\\n\\n if (numberOfValidators == 0) {\\n return address(0x0);\\n }\\n\\n uint256 validatorIndex = getLeaderIndex(numberOfValidators, _timestamp);\\n\\n return stakingBank.addresses(validatorIndex);\\n }\\n\\n /// @dev we had stack too deep in `submit` so this method was created as a solution\\n // we increasing `_consensusData.sequence` here so we don't have to read sequence again in other place\\n function _verifySubmitTimestampAndIncSequence(uint256 _dataTimestamp) internal {\\n ConsensusData memory data = _consensusData;\\n\\n // `data.lastTimestamp` must be setup either on deployment\\n // or via cloning from previous contract\\n if (data.lastTimestamp == 0) revert ContractNotReady();\\n\\n unchecked {\\n // we will not overflow with timestamp and padding in a life time\\n if (data.lastTimestamp + data.padding >= _dataTimestamp) revert BlockSubmittedToFastOrDataToOld();\\n }\\n\\n unchecked {\\n // we will not overflow in a life time\\n _consensusData.sequence = uint32(data.sequence + 1);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9eb872eaabac21d63c759e91507992710232a362afad6aa3221a8758d66f4e69\",\"license\":\"MIT\"},\"contracts/ForeignChain.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./Chain.sol\\\";\\n\\n/// @dev contract for foreign chains\\ncontract ForeignChain is Chain {\\n error NotSupported();\\n\\n /// @param _contractRegistry Registry address\\n /// @param _padding required \\\"space\\\" between blocks in seconds\\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\\n constructor(\\n IRegistry _contractRegistry,\\n uint32 _padding,\\n uint16 _requiredSignatures,\\n bool _allowForMixedType\\n ) Chain(_contractRegistry, _padding, _requiredSignatures, _allowForMixedType) {\\n // no additional configuration needed\\n }\\n\\n /// @inheritdoc BaseChain\\n function isForeign() external pure override returns (bool) {\\n return true;\\n }\\n\\n /// @inheritdoc Chain\\n /// @notice this method is made to be compatible with MasterChain, but it does not return full data eg validators\\n /// data will be missing.\\n /// @return blockNumber `block.number`\\n /// @return timePadding `this.padding`\\n /// @return lastDataTimestamp timestamp for last submitted consensus\\n /// @return lastId ID of last submitted consensus\\n /// @return nextLeader will be always address(0)\\n /// @return nextBlockId block ID for `block.timestamp + padding`\\n /// @return validators array will be always empty\\n /// @return powers array will be always empty\\n /// @return locations array will be always empty\\n /// @return staked total UMB staked by validators\\n /// @return minSignatures `this.requiredSignatures`\\n function getStatus() external view override returns(\\n uint256 blockNumber,\\n uint32 timePadding,\\n uint32 lastDataTimestamp,\\n uint32 lastId,\\n address nextLeader,\\n uint32 nextBlockId,\\n address[] memory validators,\\n uint256[] memory powers,\\n string[] memory locations,\\n uint256 staked,\\n uint16 minSignatures\\n ) {\\n ConsensusData memory data = _consensusData;\\n\\n blockNumber = block.number;\\n timePadding = data.padding;\\n lastId = data.lastTimestamp;\\n lastDataTimestamp = lastId;\\n minSignatures = _REQUIRED_SIGNATURES;\\n\\n staked = stakingBank.totalSupply();\\n uint256 numberOfValidators = 0;\\n powers = new uint256[](numberOfValidators);\\n validators = new address[](numberOfValidators);\\n locations = new string[](numberOfValidators);\\n nextLeader = address(0);\\n\\n unchecked {\\n // we will not overflow with timestamp in a lifetime\\n nextBlockId = lastId + data.padding + 1;\\n }\\n }\\n\\n function getLeaderIndex(uint256, uint256) public pure override returns (uint256) {\\n revert NotSupported();\\n }\\n\\n function getLeaderAddressAtTime(uint256) public pure override returns (address) {\\n revert NotSupported();\\n }\\n}\\n\",\"keccak256\":\"0x5b895277453aa3741c2659f335c2a4d587ff231615e4ee160bd2ec8e78778d49\",\"license\":\"MIT\"},\"contracts/Registry.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\n// Inheritance\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport \\\"./extensions/Registrable.sol\\\";\\nimport \\\"./interfaces/IRegistry.sol\\\";\\n\\n/// @dev contracts registry\\n/// protocol uses this registry to fetch current contract addresses\\ncontract Registry is IRegistry, Ownable {\\n /// name => contract address\\n mapping(bytes32 => address) public registry;\\n\\n\\n error NameNotRegistered();\\n error ArraysDataDoNotMatch();\\n\\n /// @inheritdoc IRegistry\\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external onlyOwner {\\n if (_names.length != _destinations.length) revert ArraysDataDoNotMatch();\\n\\n for (uint i = 0; i < _names.length;) {\\n registry[_names[i]] = _destinations[i];\\n emit LogRegistered(_destinations[i], _names[i]);\\n\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @inheritdoc IRegistry\\n function importContracts(address[] calldata _destinations) external onlyOwner {\\n for (uint i = 0; i < _destinations.length;) {\\n bytes32 name = Registrable(_destinations[i]).getName();\\n registry[name] = _destinations[i];\\n emit LogRegistered(_destinations[i], name);\\n\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @inheritdoc IRegistry\\n function atomicUpdate(address _newContract) external onlyOwner {\\n Registrable(_newContract).register();\\n\\n bytes32 name = Registrable(_newContract).getName();\\n address oldContract = registry[name];\\n registry[name] = _newContract;\\n\\n Registrable(oldContract).unregister();\\n\\n emit LogRegistered(_newContract, name);\\n }\\n\\n /// @inheritdoc IRegistry\\n function requireAndGetAddress(bytes32 name) external view returns (address) {\\n address _foundAddress = registry[name];\\n if (_foundAddress == address(0)) revert NameNotRegistered();\\n\\n return _foundAddress;\\n }\\n\\n /// @inheritdoc IRegistry\\n function getAddress(bytes32 _bytes) external view returns (address) {\\n return registry[_bytes];\\n }\\n\\n /// @inheritdoc IRegistry\\n function getAddressByString(string memory _name) public view returns (address) {\\n return registry[stringToBytes32(_name)];\\n }\\n\\n /// @inheritdoc IRegistry\\n function stringToBytes32(string memory _string) public pure returns (bytes32 result) {\\n bytes memory tempEmptyStringTest = bytes(_string);\\n\\n if (tempEmptyStringTest.length == 0) {\\n return 0x0;\\n }\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n result := mload(add(_string, 32))\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcf8ac18bf5766420afcc70f34339192fa67169106ccdb51573267a1ffd95fb81\",\"license\":\"MIT\"},\"contracts/extensions/Registrable.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"../interfaces/IRegistry.sol\\\";\\nimport \\\"../interfaces/IStakingBank.sol\\\";\\n\\n/// @dev Any contract that we want to register in ContractRegistry, must inherit from Registrable\\nabstract contract Registrable {\\n IRegistry public immutable contractRegistry;\\n\\n modifier onlyFromContract(address _msgSender, bytes32 _contractName) {\\n require(\\n contractRegistry.getAddress(_contractName) == _msgSender,\\n string(abi.encodePacked(\\\"caller is not \\\", _contractName))\\n );\\n _;\\n }\\n\\n modifier withRegistrySetUp() {\\n require(address(contractRegistry) != address(0x0), \\\"_registry is empty\\\");\\n _;\\n }\\n\\n constructor(IRegistry _contractRegistry) {\\n require(address(_contractRegistry) != address(0x0), \\\"_registry is empty\\\");\\n contractRegistry = _contractRegistry;\\n }\\n\\n /// @dev this method will be called as a first method in registration process when old contract will be replaced\\n /// when called, old contract address is still in registry\\n function register() virtual external;\\n\\n /// @dev this method will be called as a last method in registration process when old contract will be replaced\\n /// when called, new contract address is already in registry\\n function unregister() virtual external;\\n\\n /// @return contract name as bytes32\\n function getName() virtual external pure returns (bytes32);\\n\\n /// @dev helper method for fetching StakingBank address\\n function stakingBankContract() public view returns (IStakingBank) {\\n return IStakingBank(contractRegistry.requireAndGetAddress(\\\"StakingBank\\\"));\\n }\\n\\n /// @dev helper method for fetching UMB address\\n function tokenContract() public view withRegistrySetUp returns (ERC20) {\\n return ERC20(contractRegistry.requireAndGetAddress(\\\"UMB\\\"));\\n }\\n}\\n\",\"keccak256\":\"0x58413fc819ff8f78ba80a9339bf6b4bb818932ddef0ce58dd4813acba01bda8c\",\"license\":\"MIT\"},\"contracts/interfaces/IBaseChainV1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IBaseChainV1 {\\n /// @dev number of blocks (consensus rounds) saved in this contract\\n function blocksCount() external returns (uint32);\\n\\n /// @dev number of all blocks that were generated before switching to this contract\\n /// please note, that there might be a gap of one block when we switching from old to new contract\\n /// see constructor for details\\n function blocksCountOffset() external returns (uint32);\\n\\n function getLatestBlockId() external view returns (uint32);\\n\\n function getBlockTimestamp(uint32 _blockId) external view returns (uint32);\\n\\n function getStatus() external view returns (\\n uint256 blockNumber,\\n uint16 timePadding,\\n uint32 lastDataTimestamp,\\n uint32 lastId,\\n uint32 nextBlockId\\n );\\n}\\n\",\"keccak256\":\"0x4196faa25b921cae447328983f172ee4289591b4136fdde54ad05552c559d371\",\"license\":\"MIT\"},\"contracts/interfaces/IRegistry.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\n\\ninterface IRegistry {\\n event LogRegistered(address indexed destination, bytes32 name);\\n\\n /// @dev imports new contract addresses and override old addresses, if they exist under provided name\\n /// This method can be used for contracts that for some reason do not have `getName` method\\n /// @param _names array of contract names that we want to register\\n /// @param _destinations array of contract addresses\\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external;\\n\\n /// @dev imports new contracts and override old addresses, if they exist.\\n /// Names of contracts are fetched directly from each contract by calling `getName`\\n /// @param _destinations array of contract addresses\\n function importContracts(address[] calldata _destinations) external;\\n\\n /// @dev this method ensure, that old and new contract is aware of it state in registry\\n /// Note: BSC registry does not have this method. This method was introduced in later stage.\\n /// @param _newContract address of contract that will replace old one\\n function atomicUpdate(address _newContract) external;\\n\\n /// @dev similar to `getAddress` but throws when contract name not exists\\n /// @param name contract name\\n /// @return contract address registered under provided name or throws, if does not exists\\n function requireAndGetAddress(bytes32 name) external view returns (address);\\n\\n /// @param name contract name in a form of bytes32\\n /// @return contract address registered under provided name\\n function getAddress(bytes32 name) external view returns (address);\\n\\n /// @param _name contract name\\n /// @return contract address assigned to the name or address(0) if not exists\\n function getAddressByString(string memory _name) external view returns (address);\\n\\n /// @dev helper method that converts string to bytes32,\\n /// you can use to to generate contract name\\n function stringToBytes32(string memory _string) external pure returns (bytes32 result);\\n}\\n\",\"keccak256\":\"0xa0099ecf4182138fda7a0733407784461410c245de67c1e7ba7cd7c9595e054f\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBank.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IStakingBank is IERC20 {\\n /// @param id address of validator wallet\\n /// @param location URL of the validator API\\n struct Validator {\\n address id;\\n string location;\\n }\\n\\n event LogValidatorRegistered(address indexed id);\\n event LogValidatorUpdated(address indexed id);\\n event LogValidatorRemoved(address indexed id);\\n event LogMinAmountForStake(uint256 minAmountForStake);\\n\\n /// @dev setter for `minAmountForStake`\\n function setMinAmountForStake(uint256 _minAmountForStake) external;\\n\\n /// @dev allows to stake `token` by validators\\n /// Validator needs to approve StakingBank beforehand\\n /// @param _value amount of tokens to stake\\n function stake(uint256 _value) external;\\n\\n /// @dev notification about approval from `_from` address on UMB token\\n /// Staking bank will stake max approved amount from `_from` address\\n /// @param _from address which approved token spend for IStakingBank\\n function receiveApproval(address _from) external returns (bool success);\\n\\n /// @dev withdraws stake tokens\\n /// it throws, when balance will be less than required minimum for stake\\n /// to withdraw all use `exit`\\n function withdraw(uint256 _value) external returns (bool success);\\n\\n /// @dev unstake and withdraw all tokens\\n function exit() external returns (bool success);\\n\\n /// @dev creates (register) new validator\\n /// @param _id validator address\\n /// @param _location location URL of the validator API\\n function create(address _id, string calldata _location) external;\\n\\n /// @dev removes validator\\n /// @param _id validator wallet\\n function remove(address _id) external;\\n\\n /// @dev updates validator location\\n /// @param _id validator wallet\\n /// @param _location new validator URL\\n function update(address _id, string calldata _location) external;\\n\\n /// @return total number of registered validators (with and without balance)\\n function getNumberOfValidators() external view returns (uint256);\\n\\n /// @dev gets validator address for provided index\\n /// @param _ix index in array of list of all validators wallets\\n function addresses(uint256 _ix) external view returns (address);\\n\\n /// @param _id address of validator\\n /// @return id address of validator\\n /// @return location URL of validator\\n function validators(address _id) external view returns (address id, string memory location);\\n}\\n\",\"keccak256\":\"0x2c518aeab8b0b3a364fafaec559d3ff0dc6a119f8d203fa31ef7ad667ca0f7b9\",\"license\":\"MIT\"}},\"version\":1}", "bytecode": "0x6101006040523480156200001257600080fd5b50604051620057fa380380620057fa83398181016040528101906200003891906200067f565b838383838383838383600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603620000b3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620000aa9062000752565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250505062000108620000fc620002ee60201b60201c565b620002f660201b60201c565b80151560a0811515815250508161ffff1660c08161ffff16815250506200013583620003ba60201b60201c565b60008473ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b815260040162000170906200079a565b602060405180830381865afa1580156200018e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001b49190620007e6565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036200022b5760018442620001fb919062000847565b62000207919062000847565b600160000160086101000a81548163ffffffff021916908363ffffffff1602179055505b50505050508373ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b81526004016200026990620008a8565b602060405180830381865afa15801562000287573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002ad9190620007e6565b73ffffffffffffffffffffffffffffffffffffffff1660e08173ffffffffffffffffffffffffffffffffffffffff1681525050505050505050505062000963565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b620003ca620002ee60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16620003f06200051b60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff161462000449576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620004409062000913565b60405180910390fd5b8063ffffffff166001600001600c9054906101000a900463ffffffff1663ffffffff1603620004a4576040517f96f56f6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600001600c6101000a81548163ffffffff021916908363ffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167f02ff77a0f68d11f7efb906f331b2dda82916de8ba9c37dda2a95817936a530ec8260405162000510919062000946565b60405180910390a250565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620005768262000549565b9050919050565b60006200058a8262000569565b9050919050565b6200059c816200057d565b8114620005a857600080fd5b50565b600081519050620005bc8162000591565b92915050565b600063ffffffff82169050919050565b620005dd81620005c2565b8114620005e957600080fd5b50565b600081519050620005fd81620005d2565b92915050565b600061ffff82169050919050565b6200061c8162000603565b81146200062857600080fd5b50565b6000815190506200063c8162000611565b92915050565b60008115159050919050565b620006598162000642565b81146200066557600080fd5b50565b60008151905062000679816200064e565b92915050565b600080600080608085870312156200069c576200069b62000544565b5b6000620006ac87828801620005ab565b9450506020620006bf87828801620005ec565b9350506040620006d2878288016200062b565b9250506060620006e58782880162000668565b91505092959194509250565b600082825260208201905092915050565b7f5f726567697374727920697320656d7074790000000000000000000000000000600082015250565b60006200073a601283620006f1565b9150620007478262000702565b602082019050919050565b600060208201905081810360008301526200076d816200072b565b9050919050565b7f436861696e000000000000000000000000000000000000000000000000000000815250565b6000602082019050620007b06000830162000774565b919050565b620007c08162000569565b8114620007cc57600080fd5b50565b600081519050620007e081620007b5565b92915050565b600060208284031215620007ff57620007fe62000544565b5b60006200080f84828501620007cf565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006200085482620005c2565b91506200086183620005c2565b92508282101562000877576200087662000818565b5b828203905092915050565b7f5374616b696e6742616e6b000000000000000000000000000000000000000000815250565b6000602082019050620008be6000830162000882565b919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000620008fb602083620006f1565b91506200090882620008c3565b602082019050919050565b600060208201905081810360008301526200092e81620008ec565b9050919050565b6200094081620005c2565b82525050565b60006020820190506200095d600083018462000935565b92915050565b60805160a05160c05160e051614e02620009f860003960008181610eac015281816112260152818161145101526116880152600081816113ba015281816116650152611bd30152600061230f01526000818161082701528181610a1d01528181610ae501528181611839015281816118b00152818161194f01528181611d0b0152818161213101526122100152614e026000f3fe608060405234801561001057600080fd5b50600436106101f95760003560e01c80630f2acc3e146101fe5780630fcc0c281461022e57806317d7de7c14610238578063199dadc5146102565780631aa3a00814610286578063243b68f91461029057806324c89a49146102c057806326f3ab8b146102de57806334ba34811461030f5780633bb8819d1461032d57806340a9e5e31461035e578063485e055d1461037a5780634bc935d7146103965780634e69d560146103c657806355a373d6146103ee578063637180a81461040c5780636d046c3e1461042a578063715018a6146104485780637353cbcb1461045257806377839fe614610470578063805d34321461048e5780638d068043146104be5780638da5cb5b146104dc5780639f6119d7146104fa578063a0bc937414610518578063abf410e514610536578063adf1639d14610554578063bef9f8a114610585578063bf66e3ba146105b5578063c2a4250b146105e5578063c2b40ae414610603578063c3369db814610633578063ca4d29d214610663578063cbb1b2c714610693578063d3d3ea08146106c4578063d45167d0146106e2578063e76c0b5714610712578063e79a198f14610730578063ed9975c31461073a578063ef19f3e714610758578063f25b3f9914610788578063f2fde38b146107b8578063ffa1ad74146107d4575b600080fd5b61021860048036038101906102139190613017565b6107f2565b60405161022591906130a8565b60405180910390f35b610236610825565b005b610240610997565b60405161024d91906130a8565b60405180910390f35b610270600480360381019061026b91906131ed565b6109bf565b60405161027d91906132c3565b60405180910390f35b61028e610a1b565b005b6102aa60048036038101906102a591906132de565b610c29565b6040516102b7919061340b565b60405180910390f35b6102c8610cd2565b6040516102d591906134b5565b60405180910390f35b6102f860048036038101906102f39190613532565b610d0b565b60405161030692919061370b565b60405180910390f35b610317610eaa565b60405161032491906137c1565b60405180910390f35b610347600480360381019061034291906137dc565b610ece565b604051610355929190613831565b60405180910390f35b61037860048036038101906103739190613894565b610f63565b005b610394600480360381019061038f9190613aac565b610f73565b005b6103b060048036038101906103ab9190613bda565b611546565b6040516103bd91906132c3565b60405180910390f35b6103ce61157a565b6040516103e59b9a99989796959493929190613e5d565b60405180910390f35b6103f661181e565b6040516104039190613f3e565b60405180910390f35b61041461194b565b60405161042191906137c1565b60405180910390f35b6104326119ea565b60405161043f91906132c3565b60405180910390f35b6104506119f3565b005b61045a611a7b565b6040516104679190613f59565b60405180910390f35b610478611abe565b6040516104859190613f74565b60405180910390f35b6104a860048036038101906104a39190613f8f565b611adb565b6040516104b59190613f74565b60405180910390f35b6104c6611bcf565b6040516104d39190613fbc565b60405180910390f35b6104e4611bf7565b6040516104f19190613fd7565b60405180910390f35b610502611c20565b60405161050f9190613fd7565b60405180910390f35b610520611c3c565b60405161052d9190614069565b60405180910390f35b61053e611d09565b60405161054b91906140a5565b60405180910390f35b61056e600480360381019061056991906137dc565b611d2d565b60405161057c9291906140c0565b60405180910390f35b61059f600480360381019061059a91906140e9565b611dba565b6040516105ac91906130a8565b60405180910390f35b6105cf60048036038101906105ca91906141d9565b611ddd565b6040516105dc919061435f565b60405180910390f35b6105ed611f19565b6040516105fa9190613f59565b60405180910390f35b61061d60048036038101906106189190613f8f565b611f3c565b60405161062a91906130a8565b60405180910390f35b61064d600480360381019061064891906140e9565b611f54565b60405161065a9190613f74565b60405180910390f35b61067d60048036038101906106789190614381565b611f89565b60405161068a9190613f59565b60405180910390f35b6106ad60048036038101906106a891906137dc565b611fbd565b6040516106bb9291906143f8565b60405180910390f35b6106cc612019565b6040516106d99190613f74565b60405180910390f35b6106fc60048036038101906106f79190614421565b612036565b6040516107099190613fd7565b60405180910390f35b61071a6120f3565b6040516107279190613f74565b60405180910390f35b61073861212f565b005b6107426124b0565b60405161074f9190613fd7565b60405180910390f35b610772600480360381019061076d9190613f8f565b6124c0565b60405161077f9190613fd7565b60405180910390f35b6107a2600480360381019061079d9190613f8f565b6124f4565b6040516107af91906144b7565b60405180910390f35b6107d260048036038101906107cd91906144fe565b612531565b005b6107dc612628565b6040516107e99190613f59565b60405180910390f35b60008282604051602001610807929190614567565b60405160208183030381529060405280519060200120905092915050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156108b45750610884611bf7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156108eb576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160000160109054906101000a900460ff1615610935576040517f764c143b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018060000160106101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167fd4ae81319f0b4df100dcda9ce971671b97278c7a5ce6b37a8331a44700679fd460405160405180910390a2565b60007f436861696e000000000000000000000000000000000000000000000000000000905090565b6000610a11600260008781526020019081526020016000205484846040516020016109eb929190614567565b604051602081830303815290604052805190602001208661262d9092919063ffffffff16565b9050949350505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015610aaa5750610a7a611bf7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15610ae1576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b8152600401610b3a906145b1565b602060405180830381865afa158015610b57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7b91906145df565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610be2576040517f3a81d6fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610c1c5750610c27565b610c2581612644565b505b565b606060008267ffffffffffffffff811115610c4757610c46612eec565b5b604051908082528060200260200182016040528015610c755781602001602082028036833780820191505090505b50905060005b83811015610cc657600080602087600185010102905080880151915081848481518110610cab57610caa61460c565b5b60200260200101818152505050508080600101915050610c7b565b50809150509392505050565b6040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525081565b6060808383905067ffffffffffffffff811115610d2b57610d2a612eec565b5b604051908082528060200260200182016040528015610d595781602001602082028036833780820191505090505b5090508383905067ffffffffffffffff811115610d7957610d78612eec565b5b604051908082528060200260200182016040528015610da75781602001602082028036833780820191505090505b50915060005b84849050811015610ea257600060036000878785818110610dd157610dd061460c565b5b90506020020135815260200190815260200160002090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16848381518110610e4657610e4561460c565b5b60200260200101818152505080600001601c9054906101000a900463ffffffff16838381518110610e7a57610e7961460c565b5b602002602001019063ffffffff16908163ffffffff1681525050818060010192505050610dad565b509250929050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806000600360008581526020019081526020016000209050610f3b8160000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16612986565b81600001601c9054906101000a900463ffffffff168063ffffffff1690509250925050915091565b610f708161ffff16612a2e565b50565b610f828763ffffffff16612b79565b60008787604051602001610f97929190614692565b604051602081830303815290604052905060005b86518110156111a757858181518110610fc757610fc661460c565b5b6020026020010151868281518110610fe257610fe161460c565b5b60200260200101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff161461103f576040517f6980091000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604051806040016040528087838151811061105d5761105c61460c565b5b60200260200101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681526020018a63ffffffff16815250600360008984815181106110a9576110a861460c565b5b6020026020010151815260200190815260200160002060008201518160000160006101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff160217905550602082015181600001601c6101000a81548163ffffffff021916908363ffffffff160217905550905050818782815181106111545761115361460c565b5b602002602001015187838151811061116f5761116e61460c565b5b6020026020010151604051602001611189939291906146df565b60405160208183030381529060405291508080600101915050610fab565b506000806000838051906020012090506000805b88518110156113b7576000611220848b84815181106111dd576111dc61460c565b5b60200260200101518b85815181106111f8576111f761460c565b5b60200260200101518b86815181106112135761121261460c565b5b6020026020010151612036565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231836040518263ffffffff1660e01b815260040161127d9190613fd7565b602060405180830381865afa15801561129a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112be919061472d565b90508173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1610611325576040517f9079f69b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8193506000810361133f57828060010193505050506113b2565b868061134a90614789565b9750508173ffffffffffffffffffffffffffffffffffffffff168f63ffffffff167fbac7552ab5da8d0588709ddb75aceec28520646f54bca1cc5e6e104db61935ec8360405161139a9190613f59565b60405180910390a38086019550828060010193505050505b6111bb565b507f000000000000000000000000000000000000000000000000000000000000000061ffff16841015611416576040517fe246dc6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167f5f11830295067c4bcc7d02d4e3b048cd7427be50a3aeb6afc9d3d559ee64bcfa8d7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114de919061472d565b866040516114ee93929190614802565b60405180910390a28a600260008e63ffffffff168152602001908152602001600020819055508b600160000160086101000a81548163ffffffff021916908363ffffffff160217905550505050505050505050505050565b60008060001b830361155b5760009050611573565b61157083838661262d9092919063ffffffff16565b90505b9392505050565b6000806000806000806060806060600080600060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff1615151515815250509050439b5080606001519a50806040015198508899507f000000000000000000000000000000000000000000000000000000000000000091507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611715919061472d565b925060008067ffffffffffffffff81111561173357611732612eec565b5b6040519080825280602002602001820160405280156117615781602001602082028036833780820191505090505b5095508067ffffffffffffffff81111561177e5761177d612eec565b5b6040519080825280602002602001820160405280156117ac5781602001602082028036833780820191505090505b5096508067ffffffffffffffff8111156117c9576117c8612eec565b5b6040519080825280602002602001820160405280156117fc57816020015b60608152602001906001900390816117e75790505b50945060009850600182606001518b010197505050909192939495969798999a565b60008073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16036118ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118a590614896565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b8152600401611905906148dc565b602060405180830381865afa158015611922573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194691906145df565b905090565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b81526004016119a49061491b565b602060405180830381865afa1580156119c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e591906145df565b905090565b60006001905090565b6119fb612cf9565b73ffffffffffffffffffffffffffffffffffffffff16611a19611bf7565b73ffffffffffffffffffffffffffffffffffffffff1614611a6f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a6690614980565b60405180910390fd5b611a796000612d01565b565b6000600160000160009054906101000a900463ffffffff16600160000160049054906101000a900463ffffffff16611ab391906149a0565b63ffffffff16905090565b6000600160000160009054906101000a900463ffffffff16905090565b60008060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff161515151581525050905082816060015182604001510163ffffffff161015611bc15782915050611bca565b80604001519150505b919050565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000611c37600142611c3291906149d4565b6124c0565b905090565b611c44612e51565b60016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff161515151581525050905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060006003600085815260200190815260200160002090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681600001601c9054906101000a900463ffffffff168063ffffffff1690509250925050915091565b6000600260008363ffffffff168152602001908152602001600020549050919050565b6060815167ffffffffffffffff811115611dfa57611df9612eec565b5b604051908082528060200260200182016040528015611e285781602001602082028036833780820191505090505b5090506000805b8351811015611f0f57611ebe60026000898481518110611e5257611e5161460c565b5b602002602001015163ffffffff16815260200190815260200160002054858381518110611e8257611e8161460c565b5b6020026020010151611eaf89868a8781518110611ea257611ea161460c565b5b6020026020010151610c29565b61262d9092919063ffffffff16565b838281518110611ed157611ed061460c565b5b602002602001019015159081151581525050848181518110611ef657611ef561460c565b5b6020026020010151820191508080600101915050611e2f565b5050949350505050565b6000600160000160089054906101000a900463ffffffff1663ffffffff16905090565b60026020528060005260406000206000915090505481565b60008060001b600260008463ffffffff1681526020019081526020016000205414611f7f5781611f82565b60005b9050919050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60036020528060005260406000206000915090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169080600001601c9054906101000a900463ffffffff16905082565b6000600160000160089054906101000a900463ffffffff16905090565b6000806040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525086604051602001612081929190614a2a565b604051602081830303815290604052805190602001209050600181868686604051600081526020016040526040516120bc9493929190614a61565b6020604051602081039080840390855afa1580156120de573d6000803e3d6000fd5b50505060206040510351915050949350505050565b600080600160000160089054906101000a900463ffffffff1663ffffffff1603612120576000905061212c565b61212942611adb565b90505b90565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156121be575061218e611bf7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156121f5576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160000160109054906101000a900460ff166124ae5760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b8152600401612265906145b1565b602060405180830381865afa158015612282573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122a691906145df565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361230d576040517ff8e0084400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061244c573073ffffffffffffffffffffffffffffffffffffffff16636d046c3e6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561237d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123a19190614ad2565b15158173ffffffffffffffffffffffffffffffffffffffff16636d046c3e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124129190614ad2565b15151461244b576040517f07b72f5e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b60018060000160106101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167fd4ae81319f0b4df100dcda9ce971671b97278c7a5ce6b37a8331a44700679fd460405160405180910390a2505b565b60006124bb426124c0565b905090565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6124fc612e9a565b6040518060400160405280600260008581526020019081526020016000205481526020018363ffffffff168152509050919050565b612539612cf9565b73ffffffffffffffffffffffffffffffffffffffff16612557611bf7565b73ffffffffffffffffffffffffffffffffffffffff16146125ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125a490614980565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361261c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161261390614b71565b60405180910390fd5b61262581612d01565b50565b600281565b60008261263a8584612dc5565b1490509392505050565b6000808273ffffffffffffffffffffffffffffffffffffffff167fffa1ad74ba96b4c159a84d090433911c3991c54f629eb60d0c84aed3be5f067c60405160200161268f9190614bcc565b6040516020818303038152906040526040516126ab9190614be7565b600060405180830381855afa9150503d80600081146126e6576040519150601f19603f3d011682016040523d82523d6000602084013e6126eb565b606091505b50915091506000826126fe576001612713565b81806020019051810190612712919061472d565b5b9050600181036128935760008473ffffffffffffffffffffffffffffffffffffffff1663d3d3ea086040518163ffffffff1660e01b8152600401602060405180830381865afa15801561276a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061278e9190614c13565b90508473ffffffffffffffffffffffffffffffffffffffff1663c3369db8826040518263ffffffff1660e01b81526004016127c99190613f74565b602060405180830381865afa1580156127e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061280a9190614c13565b600160000160086101000a81548163ffffffff021916908363ffffffff16021790555060028161283a9190614c40565b600160000160046101000a81548163ffffffff021916908363ffffffff16021790555060028161286a9190614c40565b600160000160006101000a81548163ffffffff021916908363ffffffff16021790555050612980565b60008473ffffffffffffffffffffffffffffffffffffffff1663a0bc93746040518163ffffffff1660e01b815260040160a060405180830381865afa1580156128e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129049190614d0b565b90508060200151600160000160046101000a81548163ffffffff021916908363ffffffff1602179055508060200151600160000160006101000a81548163ffffffff021916908363ffffffff1602179055508060400151600160000160086101000a81548163ffffffff021916908363ffffffff160217905550505b50505050565b60008060007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff905060026001826129b99190614d38565b6129c39190614d9b565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1611612a185760008401915081601b0b92505050612a29565b600181850303915081601b0b925050505b919050565b612a36612cf9565b73ffffffffffffffffffffffffffffffffffffffff16612a54611bf7565b73ffffffffffffffffffffffffffffffffffffffff1614612aaa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612aa190614980565b60405180910390fd5b8063ffffffff166001600001600c9054906101000a900463ffffffff1663ffffffff1603612b04576040517f96f56f6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600001600c6101000a81548163ffffffff021916908363ffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167f02ff77a0f68d11f7efb906f331b2dda82916de8ba9c37dda2a95817936a530ec82604051612b6e9190613f74565b60405180910390a250565b600060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff16151515158152505090506000816040015163ffffffff1603612c81576040517f96a96e1700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81816060015182604001510163ffffffff1610612cca576040517ff886149e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001816020015101600160000160046101000a81548163ffffffff021916908363ffffffff1602179055505050565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60008082905060005b8451811015612e2f576000858281518110612dec57612deb61460c565b5b60200260200101519050808311612e0e57612e078382612e3a565b9250612e1b565b612e188184612e3a565b92505b508080612e2790614789565b915050612dce565b508091505092915050565b600082600052816020526040600020905092915050565b6040518060a00160405280600063ffffffff168152602001600063ffffffff168152602001600063ffffffff168152602001600063ffffffff1681526020016000151581525090565b604051806040016040528060008019168152602001600063ffffffff1681525090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612f2482612edb565b810181811067ffffffffffffffff82111715612f4357612f42612eec565b5b80604052505050565b6000612f56612ebd565b9050612f628282612f1b565b919050565b600067ffffffffffffffff821115612f8257612f81612eec565b5b612f8b82612edb565b9050602081019050919050565b82818337600083830152505050565b6000612fba612fb584612f67565b612f4c565b905082815260208101848484011115612fd657612fd5612ed6565b5b612fe1848285612f98565b509392505050565b600082601f830112612ffe57612ffd612ed1565b5b813561300e848260208601612fa7565b91505092915050565b6000806040838503121561302e5761302d612ec7565b5b600083013567ffffffffffffffff81111561304c5761304b612ecc565b5b61305885828601612fe9565b925050602083013567ffffffffffffffff81111561307957613078612ecc565b5b61308585828601612fe9565b9150509250929050565b6000819050919050565b6130a28161308f565b82525050565b60006020820190506130bd6000830184613099565b92915050565b6000819050919050565b6130d6816130c3565b81146130e157600080fd5b50565b6000813590506130f3816130cd565b92915050565b600067ffffffffffffffff82111561311457613113612eec565b5b602082029050602081019050919050565b600080fd5b6131338161308f565b811461313e57600080fd5b50565b6000813590506131508161312a565b92915050565b6000613169613164846130f9565b612f4c565b9050808382526020820190506020840283018581111561318c5761318b613125565b5b835b818110156131b557806131a18882613141565b84526020840193505060208101905061318e565b5050509392505050565b600082601f8301126131d4576131d3612ed1565b5b81356131e4848260208601613156565b91505092915050565b6000806000806080858703121561320757613206612ec7565b5b6000613215878288016130e4565b945050602085013567ffffffffffffffff81111561323657613235612ecc565b5b613242878288016131bf565b935050604085013567ffffffffffffffff81111561326357613262612ecc565b5b61326f87828801612fe9565b925050606085013567ffffffffffffffff8111156132905761328f612ecc565b5b61329c87828801612fe9565b91505092959194509250565b60008115159050919050565b6132bd816132a8565b82525050565b60006020820190506132d860008301846132b4565b92915050565b6000806000606084860312156132f7576132f6612ec7565b5b600084013567ffffffffffffffff81111561331557613314612ecc565b5b61332186828701612fe9565b9350506020613332868287016130e4565b9250506040613343868287016130e4565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6133828161308f565b82525050565b60006133948383613379565b60208301905092915050565b6000602082019050919050565b60006133b88261334d565b6133c28185613358565b93506133cd83613369565b8060005b838110156133fe5781516133e58882613388565b97506133f0836133a0565b9250506001810190506133d1565b5085935050505092915050565b6000602082019050818103600083015261342581846133ad565b905092915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561346757808201518184015260208101905061344c565b83811115613476576000848401525b50505050565b60006134878261342d565b6134918185613438565b93506134a1818560208601613449565b6134aa81612edb565b840191505092915050565b600060208201905081810360008301526134cf818461347c565b905092915050565b600080fd5b60008083601f8401126134f2576134f1612ed1565b5b8235905067ffffffffffffffff81111561350f5761350e6134d7565b5b60208301915083602082028301111561352b5761352a613125565b5b9250929050565b6000806020838503121561354957613548612ec7565b5b600083013567ffffffffffffffff81111561356757613566612ecc565b5b613573858286016134dc565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6135b4816130c3565b82525050565b60006135c683836135ab565b60208301905092915050565b6000602082019050919050565b60006135ea8261357f565b6135f4818561358a565b93506135ff8361359b565b8060005b8381101561363057815161361788826135ba565b9750613622836135d2565b925050600181019050613603565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600063ffffffff82169050919050565b61368281613669565b82525050565b60006136948383613679565b60208301905092915050565b6000602082019050919050565b60006136b88261363d565b6136c28185613648565b93506136cd83613659565b8060005b838110156136fe5781516136e58882613688565b97506136f0836136a0565b9250506001810190506136d1565b5085935050505092915050565b6000604082019050818103600083015261372581856135df565b9050818103602083015261373981846136ad565b90509392505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061378761378261377d84613742565b613762565b613742565b9050919050565b60006137998261376c565b9050919050565b60006137ab8261378e565b9050919050565b6137bb816137a0565b82525050565b60006020820190506137d660008301846137b2565b92915050565b6000602082840312156137f2576137f1612ec7565b5b600061380084828501613141565b91505092915050565b6000819050919050565b61381c81613809565b82525050565b61382b816130c3565b82525050565b60006040820190506138466000830185613813565b6138536020830184613822565b9392505050565b600061ffff82169050919050565b6138718161385a565b811461387c57600080fd5b50565b60008135905061388e81613868565b92915050565b6000602082840312156138aa576138a9612ec7565b5b60006138b88482850161387f565b91505092915050565b6138ca81613669565b81146138d557600080fd5b50565b6000813590506138e7816138c1565b92915050565b600067ffffffffffffffff82111561390857613907612eec565b5b602082029050602081019050919050565b600061392c613927846138ed565b612f4c565b9050808382526020820190506020840283018581111561394f5761394e613125565b5b835b81811015613978578061396488826130e4565b845260208401935050602081019050613951565b5050509392505050565b600082601f83011261399757613996612ed1565b5b81356139a7848260208601613919565b91505092915050565b600067ffffffffffffffff8211156139cb576139ca612eec565b5b602082029050602081019050919050565b600060ff82169050919050565b6139f2816139dc565b81146139fd57600080fd5b50565b600081359050613a0f816139e9565b92915050565b6000613a28613a23846139b0565b612f4c565b90508083825260208201905060208402830185811115613a4b57613a4a613125565b5b835b81811015613a745780613a608882613a00565b845260208401935050602081019050613a4d565b5050509392505050565b600082601f830112613a9357613a92612ed1565b5b8135613aa3848260208601613a15565b91505092915050565b600080600080600080600060e0888a031215613acb57613aca612ec7565b5b6000613ad98a828b016138d8565b9750506020613aea8a828b01613141565b965050604088013567ffffffffffffffff811115613b0b57613b0a612ecc565b5b613b178a828b016131bf565b955050606088013567ffffffffffffffff811115613b3857613b37612ecc565b5b613b448a828b01613982565b945050608088013567ffffffffffffffff811115613b6557613b64612ecc565b5b613b718a828b01613a7e565b93505060a088013567ffffffffffffffff811115613b9257613b91612ecc565b5b613b9e8a828b016131bf565b92505060c088013567ffffffffffffffff811115613bbf57613bbe612ecc565b5b613bcb8a828b016131bf565b91505092959891949750929550565b600080600060608486031215613bf357613bf2612ec7565b5b600084013567ffffffffffffffff811115613c1157613c10612ecc565b5b613c1d868287016131bf565b9350506020613c2e86828701613141565b9250506040613c3f86828701613141565b9150509250925092565b613c5281613669565b82525050565b6000613c6382613742565b9050919050565b613c7381613c58565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b613cae81613c58565b82525050565b6000613cc08383613ca5565b60208301905092915050565b6000602082019050919050565b6000613ce482613c79565b613cee8185613c84565b9350613cf983613c95565b8060005b83811015613d2a578151613d118882613cb4565b9750613d1c83613ccc565b925050600181019050613cfd565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b6000613d8a82613d63565b613d948185613d6e565b9350613da4818560208601613449565b613dad81612edb565b840191505092915050565b6000613dc48383613d7f565b905092915050565b6000602082019050919050565b6000613de482613d37565b613dee8185613d42565b935083602082028501613e0085613d53565b8060005b85811015613e3c5784840389528151613e1d8582613db8565b9450613e2883613dcc565b925060208a01995050600181019050613e04565b50829750879550505050505092915050565b613e578161385a565b82525050565b600061016082019050613e73600083018e613822565b613e80602083018d613c49565b613e8d604083018c613c49565b613e9a606083018b613c49565b613ea7608083018a613c6a565b613eb460a0830189613c49565b81810360c0830152613ec68188613cd9565b905081810360e0830152613eda81876135df565b9050818103610100830152613eef8186613dd9565b9050613eff610120830185613822565b613f0d610140830184613e4e565b9c9b505050505050505050505050565b6000613f288261378e565b9050919050565b613f3881613f1d565b82525050565b6000602082019050613f536000830184613f2f565b92915050565b6000602082019050613f6e6000830184613822565b92915050565b6000602082019050613f896000830184613c49565b92915050565b600060208284031215613fa557613fa4612ec7565b5b6000613fb3848285016130e4565b91505092915050565b6000602082019050613fd16000830184613e4e565b92915050565b6000602082019050613fec6000830184613c6a565b92915050565b613ffb816132a8565b82525050565b60a0820160008201516140176000850182613679565b50602082015161402a6020850182613679565b50604082015161403d6040850182613679565b5060608201516140506060850182613679565b5060808201516140636080850182613ff2565b50505050565b600060a08201905061407e6000830184614001565b92915050565b600061408f8261378e565b9050919050565b61409f81614084565b82525050565b60006020820190506140ba6000830184614096565b92915050565b60006040820190506140d56000830185613822565b6140e26020830184613822565b9392505050565b6000602082840312156140ff576140fe612ec7565b5b600061410d848285016138d8565b91505092915050565b600067ffffffffffffffff82111561413157614130612eec565b5b602082029050602081019050919050565b600061415561415084614116565b612f4c565b9050808382526020820190506020840283018581111561417857614177613125565b5b835b818110156141a1578061418d88826138d8565b84526020840193505060208101905061417a565b5050509392505050565b600082601f8301126141c0576141bf612ed1565b5b81356141d0848260208601614142565b91505092915050565b600080600080608085870312156141f3576141f2612ec7565b5b600085013567ffffffffffffffff81111561421157614210612ecc565b5b61421d878288016141ab565b945050602085013567ffffffffffffffff81111561423e5761423d612ecc565b5b61424a87828801612fe9565b935050604085013567ffffffffffffffff81111561426b5761426a612ecc565b5b61427787828801613982565b925050606085013567ffffffffffffffff81111561429857614297612ecc565b5b6142a4878288016131bf565b91505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60006142e88383613ff2565b60208301905092915050565b6000602082019050919050565b600061430c826142b0565b61431681856142bb565b9350614321836142cc565b8060005b8381101561435257815161433988826142dc565b9750614344836142f4565b925050600181019050614325565b5085935050505092915050565b600060208201905081810360008301526143798184614301565b905092915050565b6000806040838503121561439857614397612ec7565b5b60006143a6858286016130e4565b92505060206143b7858286016130e4565b9150509250929050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff82169050919050565b6143f2816143c1565b82525050565b600060408201905061440d60008301856143e9565b61441a6020830184613c49565b9392505050565b6000806000806080858703121561443b5761443a612ec7565b5b600061444987828801613141565b945050602061445a87828801613a00565b935050604061446b87828801613141565b925050606061447c87828801613141565b91505092959194509250565b60408201600082015161449e6000850182613379565b5060208201516144b16020850182613679565b50505050565b60006040820190506144cc6000830184614488565b92915050565b6144db81613c58565b81146144e657600080fd5b50565b6000813590506144f8816144d2565b92915050565b60006020828403121561451457614513612ec7565b5b6000614522848285016144e9565b91505092915050565b600081905092915050565b60006145418261342d565b61454b818561452b565b935061455b818560208601613449565b80840191505092915050565b60006145738285614536565b915061457f8284614536565b91508190509392505050565b7f436861696e000000000000000000000000000000000000000000000000000000815250565b60006020820190506145c56000830161458b565b919050565b6000815190506145d9816144d2565b92915050565b6000602082840312156145f5576145f4612ec7565b5b6000614603848285016145ca565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008160e01b9050919050565b60006146538261463b565b9050919050565b61466b61466682613669565b614648565b82525050565b6000819050919050565b61468c6146878261308f565b614671565b82525050565b600061469e828561465a565b6004820191506146ae828461467b565b6020820191508190509392505050565b6000819050919050565b6146d96146d4826130c3565b6146be565b82525050565b60006146eb8286614536565b91506146f7828561467b565b60208201915061470782846146c8565b602082019150819050949350505050565b600081519050614727816130cd565b92915050565b60006020828403121561474357614742612ec7565b5b600061475184828501614718565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614794826130c3565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036147c6576147c561475a565b5b600182019050919050565b60006147ec6147e76147e284613669565b613762565b6130c3565b9050919050565b6147fc816147d1565b82525050565b600060608201905061481760008301866147f3565b6148246020830185613822565b6148316040830184613822565b949350505050565b600082825260208201905092915050565b7f5f726567697374727920697320656d7074790000000000000000000000000000600082015250565b6000614880601283614839565b915061488b8261484a565b602082019050919050565b600060208201905081810360008301526148af81614873565b9050919050565b7f554d420000000000000000000000000000000000000000000000000000000000815250565b60006020820190506148f0600083016148b6565b919050565b7f5374616b696e6742616e6b000000000000000000000000000000000000000000815250565b600060208201905061492f600083016148f5565b919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600061496a602083614839565b915061497582614934565b602082019050919050565b600060208201905081810360008301526149998161495d565b9050919050565b60006149ab82613669565b91506149b683613669565b9250828210156149c9576149c861475a565b5b828203905092915050565b60006149df826130c3565b91506149ea836130c3565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115614a1f57614a1e61475a565b5b828201905092915050565b6000614a368285614536565b9150614a42828461467b565b6020820191508190509392505050565b614a5b816139dc565b82525050565b6000608082019050614a766000830187613099565b614a836020830186614a52565b614a906040830185613099565b614a9d6060830184613099565b95945050505050565b614aaf816132a8565b8114614aba57600080fd5b50565b600081519050614acc81614aa6565b92915050565b600060208284031215614ae857614ae7612ec7565b5b6000614af684828501614abd565b91505092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000614b5b602683614839565b9150614b6682614aff565b604082019050919050565b60006020820190508181036000830152614b8a81614b4e565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b614bc681614b91565b82525050565b6000602082019050614be16000830184614bbd565b92915050565b6000614bf38284614536565b915081905092915050565b600081519050614c0d816138c1565b92915050565b600060208284031215614c2957614c28612ec7565b5b6000614c3784828501614bfe565b91505092915050565b6000614c4b82613669565b9150614c5683613669565b92508263ffffffff03821115614c6f57614c6e61475a565b5b828201905092915050565b600080fd5b600060a08284031215614c9557614c94614c7a565b5b614c9f60a0612f4c565b90506000614caf84828501614bfe565b6000830152506020614cc384828501614bfe565b6020830152506040614cd784828501614bfe565b6040830152506060614ceb84828501614bfe565b6060830152506080614cff84828501614abd565b60808301525092915050565b600060a08284031215614d2157614d20612ec7565b5b6000614d2f84828501614c7f565b91505092915050565b6000614d43826143c1565b9150614d4e836143c1565b925082821015614d6157614d6061475a565b5b828203905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614da6826143c1565b9150614db1836143c1565b925082614dc157614dc0614d6c565b5b82820490509291505056fea2646970667358221220c360ae03d3a676b33b3c5097d3c8e8893865decc08d54266712bbb98da90469d64736f6c634300080d0033", "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101f95760003560e01c80630f2acc3e146101fe5780630fcc0c281461022e57806317d7de7c14610238578063199dadc5146102565780631aa3a00814610286578063243b68f91461029057806324c89a49146102c057806326f3ab8b146102de57806334ba34811461030f5780633bb8819d1461032d57806340a9e5e31461035e578063485e055d1461037a5780634bc935d7146103965780634e69d560146103c657806355a373d6146103ee578063637180a81461040c5780636d046c3e1461042a578063715018a6146104485780637353cbcb1461045257806377839fe614610470578063805d34321461048e5780638d068043146104be5780638da5cb5b146104dc5780639f6119d7146104fa578063a0bc937414610518578063abf410e514610536578063adf1639d14610554578063bef9f8a114610585578063bf66e3ba146105b5578063c2a4250b146105e5578063c2b40ae414610603578063c3369db814610633578063ca4d29d214610663578063cbb1b2c714610693578063d3d3ea08146106c4578063d45167d0146106e2578063e76c0b5714610712578063e79a198f14610730578063ed9975c31461073a578063ef19f3e714610758578063f25b3f9914610788578063f2fde38b146107b8578063ffa1ad74146107d4575b600080fd5b61021860048036038101906102139190613017565b6107f2565b60405161022591906130a8565b60405180910390f35b610236610825565b005b610240610997565b60405161024d91906130a8565b60405180910390f35b610270600480360381019061026b91906131ed565b6109bf565b60405161027d91906132c3565b60405180910390f35b61028e610a1b565b005b6102aa60048036038101906102a591906132de565b610c29565b6040516102b7919061340b565b60405180910390f35b6102c8610cd2565b6040516102d591906134b5565b60405180910390f35b6102f860048036038101906102f39190613532565b610d0b565b60405161030692919061370b565b60405180910390f35b610317610eaa565b60405161032491906137c1565b60405180910390f35b610347600480360381019061034291906137dc565b610ece565b604051610355929190613831565b60405180910390f35b61037860048036038101906103739190613894565b610f63565b005b610394600480360381019061038f9190613aac565b610f73565b005b6103b060048036038101906103ab9190613bda565b611546565b6040516103bd91906132c3565b60405180910390f35b6103ce61157a565b6040516103e59b9a99989796959493929190613e5d565b60405180910390f35b6103f661181e565b6040516104039190613f3e565b60405180910390f35b61041461194b565b60405161042191906137c1565b60405180910390f35b6104326119ea565b60405161043f91906132c3565b60405180910390f35b6104506119f3565b005b61045a611a7b565b6040516104679190613f59565b60405180910390f35b610478611abe565b6040516104859190613f74565b60405180910390f35b6104a860048036038101906104a39190613f8f565b611adb565b6040516104b59190613f74565b60405180910390f35b6104c6611bcf565b6040516104d39190613fbc565b60405180910390f35b6104e4611bf7565b6040516104f19190613fd7565b60405180910390f35b610502611c20565b60405161050f9190613fd7565b60405180910390f35b610520611c3c565b60405161052d9190614069565b60405180910390f35b61053e611d09565b60405161054b91906140a5565b60405180910390f35b61056e600480360381019061056991906137dc565b611d2d565b60405161057c9291906140c0565b60405180910390f35b61059f600480360381019061059a91906140e9565b611dba565b6040516105ac91906130a8565b60405180910390f35b6105cf60048036038101906105ca91906141d9565b611ddd565b6040516105dc919061435f565b60405180910390f35b6105ed611f19565b6040516105fa9190613f59565b60405180910390f35b61061d60048036038101906106189190613f8f565b611f3c565b60405161062a91906130a8565b60405180910390f35b61064d600480360381019061064891906140e9565b611f54565b60405161065a9190613f74565b60405180910390f35b61067d60048036038101906106789190614381565b611f89565b60405161068a9190613f59565b60405180910390f35b6106ad60048036038101906106a891906137dc565b611fbd565b6040516106bb9291906143f8565b60405180910390f35b6106cc612019565b6040516106d99190613f74565b60405180910390f35b6106fc60048036038101906106f79190614421565b612036565b6040516107099190613fd7565b60405180910390f35b61071a6120f3565b6040516107279190613f74565b60405180910390f35b61073861212f565b005b6107426124b0565b60405161074f9190613fd7565b60405180910390f35b610772600480360381019061076d9190613f8f565b6124c0565b60405161077f9190613fd7565b60405180910390f35b6107a2600480360381019061079d9190613f8f565b6124f4565b6040516107af91906144b7565b60405180910390f35b6107d260048036038101906107cd91906144fe565b612531565b005b6107dc612628565b6040516107e99190613f59565b60405180910390f35b60008282604051602001610807929190614567565b60405160208183030381529060405280519060200120905092915050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156108b45750610884611bf7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156108eb576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160000160109054906101000a900460ff1615610935576040517f764c143b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018060000160106101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167fd4ae81319f0b4df100dcda9ce971671b97278c7a5ce6b37a8331a44700679fd460405160405180910390a2565b60007f436861696e000000000000000000000000000000000000000000000000000000905090565b6000610a11600260008781526020019081526020016000205484846040516020016109eb929190614567565b604051602081830303815290604052805190602001208661262d9092919063ffffffff16565b9050949350505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015610aaa5750610a7a611bf7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15610ae1576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b8152600401610b3a906145b1565b602060405180830381865afa158015610b57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7b91906145df565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610be2576040517f3a81d6fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610c1c5750610c27565b610c2581612644565b505b565b606060008267ffffffffffffffff811115610c4757610c46612eec565b5b604051908082528060200260200182016040528015610c755781602001602082028036833780820191505090505b50905060005b83811015610cc657600080602087600185010102905080880151915081848481518110610cab57610caa61460c565b5b60200260200101818152505050508080600101915050610c7b565b50809150509392505050565b6040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525081565b6060808383905067ffffffffffffffff811115610d2b57610d2a612eec565b5b604051908082528060200260200182016040528015610d595781602001602082028036833780820191505090505b5090508383905067ffffffffffffffff811115610d7957610d78612eec565b5b604051908082528060200260200182016040528015610da75781602001602082028036833780820191505090505b50915060005b84849050811015610ea257600060036000878785818110610dd157610dd061460c565b5b90506020020135815260200190815260200160002090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16848381518110610e4657610e4561460c565b5b60200260200101818152505080600001601c9054906101000a900463ffffffff16838381518110610e7a57610e7961460c565b5b602002602001019063ffffffff16908163ffffffff1681525050818060010192505050610dad565b509250929050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806000600360008581526020019081526020016000209050610f3b8160000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16612986565b81600001601c9054906101000a900463ffffffff168063ffffffff1690509250925050915091565b610f708161ffff16612a2e565b50565b610f828763ffffffff16612b79565b60008787604051602001610f97929190614692565b604051602081830303815290604052905060005b86518110156111a757858181518110610fc757610fc661460c565b5b6020026020010151868281518110610fe257610fe161460c565b5b60200260200101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff161461103f576040517f6980091000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604051806040016040528087838151811061105d5761105c61460c565b5b60200260200101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681526020018a63ffffffff16815250600360008984815181106110a9576110a861460c565b5b6020026020010151815260200190815260200160002060008201518160000160006101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff160217905550602082015181600001601c6101000a81548163ffffffff021916908363ffffffff160217905550905050818782815181106111545761115361460c565b5b602002602001015187838151811061116f5761116e61460c565b5b6020026020010151604051602001611189939291906146df565b60405160208183030381529060405291508080600101915050610fab565b506000806000838051906020012090506000805b88518110156113b7576000611220848b84815181106111dd576111dc61460c565b5b60200260200101518b85815181106111f8576111f761460c565b5b60200260200101518b86815181106112135761121261460c565b5b6020026020010151612036565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231836040518263ffffffff1660e01b815260040161127d9190613fd7565b602060405180830381865afa15801561129a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112be919061472d565b90508173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1610611325576040517f9079f69b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8193506000810361133f57828060010193505050506113b2565b868061134a90614789565b9750508173ffffffffffffffffffffffffffffffffffffffff168f63ffffffff167fbac7552ab5da8d0588709ddb75aceec28520646f54bca1cc5e6e104db61935ec8360405161139a9190613f59565b60405180910390a38086019550828060010193505050505b6111bb565b507f000000000000000000000000000000000000000000000000000000000000000061ffff16841015611416576040517fe246dc6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167f5f11830295067c4bcc7d02d4e3b048cd7427be50a3aeb6afc9d3d559ee64bcfa8d7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114de919061472d565b866040516114ee93929190614802565b60405180910390a28a600260008e63ffffffff168152602001908152602001600020819055508b600160000160086101000a81548163ffffffff021916908363ffffffff160217905550505050505050505050505050565b60008060001b830361155b5760009050611573565b61157083838661262d9092919063ffffffff16565b90505b9392505050565b6000806000806000806060806060600080600060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff1615151515815250509050439b5080606001519a50806040015198508899507f000000000000000000000000000000000000000000000000000000000000000091507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611715919061472d565b925060008067ffffffffffffffff81111561173357611732612eec565b5b6040519080825280602002602001820160405280156117615781602001602082028036833780820191505090505b5095508067ffffffffffffffff81111561177e5761177d612eec565b5b6040519080825280602002602001820160405280156117ac5781602001602082028036833780820191505090505b5096508067ffffffffffffffff8111156117c9576117c8612eec565b5b6040519080825280602002602001820160405280156117fc57816020015b60608152602001906001900390816117e75790505b50945060009850600182606001518b010197505050909192939495969798999a565b60008073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16036118ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118a590614896565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b8152600401611905906148dc565b602060405180830381865afa158015611922573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194691906145df565b905090565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b81526004016119a49061491b565b602060405180830381865afa1580156119c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e591906145df565b905090565b60006001905090565b6119fb612cf9565b73ffffffffffffffffffffffffffffffffffffffff16611a19611bf7565b73ffffffffffffffffffffffffffffffffffffffff1614611a6f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a6690614980565b60405180910390fd5b611a796000612d01565b565b6000600160000160009054906101000a900463ffffffff16600160000160049054906101000a900463ffffffff16611ab391906149a0565b63ffffffff16905090565b6000600160000160009054906101000a900463ffffffff16905090565b60008060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff161515151581525050905082816060015182604001510163ffffffff161015611bc15782915050611bca565b80604001519150505b919050565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000611c37600142611c3291906149d4565b6124c0565b905090565b611c44612e51565b60016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff161515151581525050905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060006003600085815260200190815260200160002090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681600001601c9054906101000a900463ffffffff168063ffffffff1690509250925050915091565b6000600260008363ffffffff168152602001908152602001600020549050919050565b6060815167ffffffffffffffff811115611dfa57611df9612eec565b5b604051908082528060200260200182016040528015611e285781602001602082028036833780820191505090505b5090506000805b8351811015611f0f57611ebe60026000898481518110611e5257611e5161460c565b5b602002602001015163ffffffff16815260200190815260200160002054858381518110611e8257611e8161460c565b5b6020026020010151611eaf89868a8781518110611ea257611ea161460c565b5b6020026020010151610c29565b61262d9092919063ffffffff16565b838281518110611ed157611ed061460c565b5b602002602001019015159081151581525050848181518110611ef657611ef561460c565b5b6020026020010151820191508080600101915050611e2f565b5050949350505050565b6000600160000160089054906101000a900463ffffffff1663ffffffff16905090565b60026020528060005260406000206000915090505481565b60008060001b600260008463ffffffff1681526020019081526020016000205414611f7f5781611f82565b60005b9050919050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60036020528060005260406000206000915090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169080600001601c9054906101000a900463ffffffff16905082565b6000600160000160089054906101000a900463ffffffff16905090565b6000806040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525086604051602001612081929190614a2a565b604051602081830303815290604052805190602001209050600181868686604051600081526020016040526040516120bc9493929190614a61565b6020604051602081039080840390855afa1580156120de573d6000803e3d6000fd5b50505060206040510351915050949350505050565b600080600160000160089054906101000a900463ffffffff1663ffffffff1603612120576000905061212c565b61212942611adb565b90505b90565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156121be575061218e611bf7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156121f5576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160000160109054906101000a900460ff166124ae5760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b8152600401612265906145b1565b602060405180830381865afa158015612282573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122a691906145df565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361230d576040517ff8e0084400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061244c573073ffffffffffffffffffffffffffffffffffffffff16636d046c3e6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561237d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123a19190614ad2565b15158173ffffffffffffffffffffffffffffffffffffffff16636d046c3e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124129190614ad2565b15151461244b576040517f07b72f5e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b60018060000160106101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167fd4ae81319f0b4df100dcda9ce971671b97278c7a5ce6b37a8331a44700679fd460405160405180910390a2505b565b60006124bb426124c0565b905090565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6124fc612e9a565b6040518060400160405280600260008581526020019081526020016000205481526020018363ffffffff168152509050919050565b612539612cf9565b73ffffffffffffffffffffffffffffffffffffffff16612557611bf7565b73ffffffffffffffffffffffffffffffffffffffff16146125ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125a490614980565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361261c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161261390614b71565b60405180910390fd5b61262581612d01565b50565b600281565b60008261263a8584612dc5565b1490509392505050565b6000808273ffffffffffffffffffffffffffffffffffffffff167fffa1ad74ba96b4c159a84d090433911c3991c54f629eb60d0c84aed3be5f067c60405160200161268f9190614bcc565b6040516020818303038152906040526040516126ab9190614be7565b600060405180830381855afa9150503d80600081146126e6576040519150601f19603f3d011682016040523d82523d6000602084013e6126eb565b606091505b50915091506000826126fe576001612713565b81806020019051810190612712919061472d565b5b9050600181036128935760008473ffffffffffffffffffffffffffffffffffffffff1663d3d3ea086040518163ffffffff1660e01b8152600401602060405180830381865afa15801561276a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061278e9190614c13565b90508473ffffffffffffffffffffffffffffffffffffffff1663c3369db8826040518263ffffffff1660e01b81526004016127c99190613f74565b602060405180830381865afa1580156127e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061280a9190614c13565b600160000160086101000a81548163ffffffff021916908363ffffffff16021790555060028161283a9190614c40565b600160000160046101000a81548163ffffffff021916908363ffffffff16021790555060028161286a9190614c40565b600160000160006101000a81548163ffffffff021916908363ffffffff16021790555050612980565b60008473ffffffffffffffffffffffffffffffffffffffff1663a0bc93746040518163ffffffff1660e01b815260040160a060405180830381865afa1580156128e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129049190614d0b565b90508060200151600160000160046101000a81548163ffffffff021916908363ffffffff1602179055508060200151600160000160006101000a81548163ffffffff021916908363ffffffff1602179055508060400151600160000160086101000a81548163ffffffff021916908363ffffffff160217905550505b50505050565b60008060007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff905060026001826129b99190614d38565b6129c39190614d9b565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1611612a185760008401915081601b0b92505050612a29565b600181850303915081601b0b925050505b919050565b612a36612cf9565b73ffffffffffffffffffffffffffffffffffffffff16612a54611bf7565b73ffffffffffffffffffffffffffffffffffffffff1614612aaa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612aa190614980565b60405180910390fd5b8063ffffffff166001600001600c9054906101000a900463ffffffff1663ffffffff1603612b04576040517f96f56f6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600001600c6101000a81548163ffffffff021916908363ffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167f02ff77a0f68d11f7efb906f331b2dda82916de8ba9c37dda2a95817936a530ec82604051612b6e9190613f74565b60405180910390a250565b600060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff16151515158152505090506000816040015163ffffffff1603612c81576040517f96a96e1700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81816060015182604001510163ffffffff1610612cca576040517ff886149e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001816020015101600160000160046101000a81548163ffffffff021916908363ffffffff1602179055505050565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60008082905060005b8451811015612e2f576000858281518110612dec57612deb61460c565b5b60200260200101519050808311612e0e57612e078382612e3a565b9250612e1b565b612e188184612e3a565b92505b508080612e2790614789565b915050612dce565b508091505092915050565b600082600052816020526040600020905092915050565b6040518060a00160405280600063ffffffff168152602001600063ffffffff168152602001600063ffffffff168152602001600063ffffffff1681526020016000151581525090565b604051806040016040528060008019168152602001600063ffffffff1681525090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612f2482612edb565b810181811067ffffffffffffffff82111715612f4357612f42612eec565b5b80604052505050565b6000612f56612ebd565b9050612f628282612f1b565b919050565b600067ffffffffffffffff821115612f8257612f81612eec565b5b612f8b82612edb565b9050602081019050919050565b82818337600083830152505050565b6000612fba612fb584612f67565b612f4c565b905082815260208101848484011115612fd657612fd5612ed6565b5b612fe1848285612f98565b509392505050565b600082601f830112612ffe57612ffd612ed1565b5b813561300e848260208601612fa7565b91505092915050565b6000806040838503121561302e5761302d612ec7565b5b600083013567ffffffffffffffff81111561304c5761304b612ecc565b5b61305885828601612fe9565b925050602083013567ffffffffffffffff81111561307957613078612ecc565b5b61308585828601612fe9565b9150509250929050565b6000819050919050565b6130a28161308f565b82525050565b60006020820190506130bd6000830184613099565b92915050565b6000819050919050565b6130d6816130c3565b81146130e157600080fd5b50565b6000813590506130f3816130cd565b92915050565b600067ffffffffffffffff82111561311457613113612eec565b5b602082029050602081019050919050565b600080fd5b6131338161308f565b811461313e57600080fd5b50565b6000813590506131508161312a565b92915050565b6000613169613164846130f9565b612f4c565b9050808382526020820190506020840283018581111561318c5761318b613125565b5b835b818110156131b557806131a18882613141565b84526020840193505060208101905061318e565b5050509392505050565b600082601f8301126131d4576131d3612ed1565b5b81356131e4848260208601613156565b91505092915050565b6000806000806080858703121561320757613206612ec7565b5b6000613215878288016130e4565b945050602085013567ffffffffffffffff81111561323657613235612ecc565b5b613242878288016131bf565b935050604085013567ffffffffffffffff81111561326357613262612ecc565b5b61326f87828801612fe9565b925050606085013567ffffffffffffffff8111156132905761328f612ecc565b5b61329c87828801612fe9565b91505092959194509250565b60008115159050919050565b6132bd816132a8565b82525050565b60006020820190506132d860008301846132b4565b92915050565b6000806000606084860312156132f7576132f6612ec7565b5b600084013567ffffffffffffffff81111561331557613314612ecc565b5b61332186828701612fe9565b9350506020613332868287016130e4565b9250506040613343868287016130e4565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6133828161308f565b82525050565b60006133948383613379565b60208301905092915050565b6000602082019050919050565b60006133b88261334d565b6133c28185613358565b93506133cd83613369565b8060005b838110156133fe5781516133e58882613388565b97506133f0836133a0565b9250506001810190506133d1565b5085935050505092915050565b6000602082019050818103600083015261342581846133ad565b905092915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561346757808201518184015260208101905061344c565b83811115613476576000848401525b50505050565b60006134878261342d565b6134918185613438565b93506134a1818560208601613449565b6134aa81612edb565b840191505092915050565b600060208201905081810360008301526134cf818461347c565b905092915050565b600080fd5b60008083601f8401126134f2576134f1612ed1565b5b8235905067ffffffffffffffff81111561350f5761350e6134d7565b5b60208301915083602082028301111561352b5761352a613125565b5b9250929050565b6000806020838503121561354957613548612ec7565b5b600083013567ffffffffffffffff81111561356757613566612ecc565b5b613573858286016134dc565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6135b4816130c3565b82525050565b60006135c683836135ab565b60208301905092915050565b6000602082019050919050565b60006135ea8261357f565b6135f4818561358a565b93506135ff8361359b565b8060005b8381101561363057815161361788826135ba565b9750613622836135d2565b925050600181019050613603565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600063ffffffff82169050919050565b61368281613669565b82525050565b60006136948383613679565b60208301905092915050565b6000602082019050919050565b60006136b88261363d565b6136c28185613648565b93506136cd83613659565b8060005b838110156136fe5781516136e58882613688565b97506136f0836136a0565b9250506001810190506136d1565b5085935050505092915050565b6000604082019050818103600083015261372581856135df565b9050818103602083015261373981846136ad565b90509392505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061378761378261377d84613742565b613762565b613742565b9050919050565b60006137998261376c565b9050919050565b60006137ab8261378e565b9050919050565b6137bb816137a0565b82525050565b60006020820190506137d660008301846137b2565b92915050565b6000602082840312156137f2576137f1612ec7565b5b600061380084828501613141565b91505092915050565b6000819050919050565b61381c81613809565b82525050565b61382b816130c3565b82525050565b60006040820190506138466000830185613813565b6138536020830184613822565b9392505050565b600061ffff82169050919050565b6138718161385a565b811461387c57600080fd5b50565b60008135905061388e81613868565b92915050565b6000602082840312156138aa576138a9612ec7565b5b60006138b88482850161387f565b91505092915050565b6138ca81613669565b81146138d557600080fd5b50565b6000813590506138e7816138c1565b92915050565b600067ffffffffffffffff82111561390857613907612eec565b5b602082029050602081019050919050565b600061392c613927846138ed565b612f4c565b9050808382526020820190506020840283018581111561394f5761394e613125565b5b835b81811015613978578061396488826130e4565b845260208401935050602081019050613951565b5050509392505050565b600082601f83011261399757613996612ed1565b5b81356139a7848260208601613919565b91505092915050565b600067ffffffffffffffff8211156139cb576139ca612eec565b5b602082029050602081019050919050565b600060ff82169050919050565b6139f2816139dc565b81146139fd57600080fd5b50565b600081359050613a0f816139e9565b92915050565b6000613a28613a23846139b0565b612f4c565b90508083825260208201905060208402830185811115613a4b57613a4a613125565b5b835b81811015613a745780613a608882613a00565b845260208401935050602081019050613a4d565b5050509392505050565b600082601f830112613a9357613a92612ed1565b5b8135613aa3848260208601613a15565b91505092915050565b600080600080600080600060e0888a031215613acb57613aca612ec7565b5b6000613ad98a828b016138d8565b9750506020613aea8a828b01613141565b965050604088013567ffffffffffffffff811115613b0b57613b0a612ecc565b5b613b178a828b016131bf565b955050606088013567ffffffffffffffff811115613b3857613b37612ecc565b5b613b448a828b01613982565b945050608088013567ffffffffffffffff811115613b6557613b64612ecc565b5b613b718a828b01613a7e565b93505060a088013567ffffffffffffffff811115613b9257613b91612ecc565b5b613b9e8a828b016131bf565b92505060c088013567ffffffffffffffff811115613bbf57613bbe612ecc565b5b613bcb8a828b016131bf565b91505092959891949750929550565b600080600060608486031215613bf357613bf2612ec7565b5b600084013567ffffffffffffffff811115613c1157613c10612ecc565b5b613c1d868287016131bf565b9350506020613c2e86828701613141565b9250506040613c3f86828701613141565b9150509250925092565b613c5281613669565b82525050565b6000613c6382613742565b9050919050565b613c7381613c58565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b613cae81613c58565b82525050565b6000613cc08383613ca5565b60208301905092915050565b6000602082019050919050565b6000613ce482613c79565b613cee8185613c84565b9350613cf983613c95565b8060005b83811015613d2a578151613d118882613cb4565b9750613d1c83613ccc565b925050600181019050613cfd565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b6000613d8a82613d63565b613d948185613d6e565b9350613da4818560208601613449565b613dad81612edb565b840191505092915050565b6000613dc48383613d7f565b905092915050565b6000602082019050919050565b6000613de482613d37565b613dee8185613d42565b935083602082028501613e0085613d53565b8060005b85811015613e3c5784840389528151613e1d8582613db8565b9450613e2883613dcc565b925060208a01995050600181019050613e04565b50829750879550505050505092915050565b613e578161385a565b82525050565b600061016082019050613e73600083018e613822565b613e80602083018d613c49565b613e8d604083018c613c49565b613e9a606083018b613c49565b613ea7608083018a613c6a565b613eb460a0830189613c49565b81810360c0830152613ec68188613cd9565b905081810360e0830152613eda81876135df565b9050818103610100830152613eef8186613dd9565b9050613eff610120830185613822565b613f0d610140830184613e4e565b9c9b505050505050505050505050565b6000613f288261378e565b9050919050565b613f3881613f1d565b82525050565b6000602082019050613f536000830184613f2f565b92915050565b6000602082019050613f6e6000830184613822565b92915050565b6000602082019050613f896000830184613c49565b92915050565b600060208284031215613fa557613fa4612ec7565b5b6000613fb3848285016130e4565b91505092915050565b6000602082019050613fd16000830184613e4e565b92915050565b6000602082019050613fec6000830184613c6a565b92915050565b613ffb816132a8565b82525050565b60a0820160008201516140176000850182613679565b50602082015161402a6020850182613679565b50604082015161403d6040850182613679565b5060608201516140506060850182613679565b5060808201516140636080850182613ff2565b50505050565b600060a08201905061407e6000830184614001565b92915050565b600061408f8261378e565b9050919050565b61409f81614084565b82525050565b60006020820190506140ba6000830184614096565b92915050565b60006040820190506140d56000830185613822565b6140e26020830184613822565b9392505050565b6000602082840312156140ff576140fe612ec7565b5b600061410d848285016138d8565b91505092915050565b600067ffffffffffffffff82111561413157614130612eec565b5b602082029050602081019050919050565b600061415561415084614116565b612f4c565b9050808382526020820190506020840283018581111561417857614177613125565b5b835b818110156141a1578061418d88826138d8565b84526020840193505060208101905061417a565b5050509392505050565b600082601f8301126141c0576141bf612ed1565b5b81356141d0848260208601614142565b91505092915050565b600080600080608085870312156141f3576141f2612ec7565b5b600085013567ffffffffffffffff81111561421157614210612ecc565b5b61421d878288016141ab565b945050602085013567ffffffffffffffff81111561423e5761423d612ecc565b5b61424a87828801612fe9565b935050604085013567ffffffffffffffff81111561426b5761426a612ecc565b5b61427787828801613982565b925050606085013567ffffffffffffffff81111561429857614297612ecc565b5b6142a4878288016131bf565b91505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60006142e88383613ff2565b60208301905092915050565b6000602082019050919050565b600061430c826142b0565b61431681856142bb565b9350614321836142cc565b8060005b8381101561435257815161433988826142dc565b9750614344836142f4565b925050600181019050614325565b5085935050505092915050565b600060208201905081810360008301526143798184614301565b905092915050565b6000806040838503121561439857614397612ec7565b5b60006143a6858286016130e4565b92505060206143b7858286016130e4565b9150509250929050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff82169050919050565b6143f2816143c1565b82525050565b600060408201905061440d60008301856143e9565b61441a6020830184613c49565b9392505050565b6000806000806080858703121561443b5761443a612ec7565b5b600061444987828801613141565b945050602061445a87828801613a00565b935050604061446b87828801613141565b925050606061447c87828801613141565b91505092959194509250565b60408201600082015161449e6000850182613379565b5060208201516144b16020850182613679565b50505050565b60006040820190506144cc6000830184614488565b92915050565b6144db81613c58565b81146144e657600080fd5b50565b6000813590506144f8816144d2565b92915050565b60006020828403121561451457614513612ec7565b5b6000614522848285016144e9565b91505092915050565b600081905092915050565b60006145418261342d565b61454b818561452b565b935061455b818560208601613449565b80840191505092915050565b60006145738285614536565b915061457f8284614536565b91508190509392505050565b7f436861696e000000000000000000000000000000000000000000000000000000815250565b60006020820190506145c56000830161458b565b919050565b6000815190506145d9816144d2565b92915050565b6000602082840312156145f5576145f4612ec7565b5b6000614603848285016145ca565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008160e01b9050919050565b60006146538261463b565b9050919050565b61466b61466682613669565b614648565b82525050565b6000819050919050565b61468c6146878261308f565b614671565b82525050565b600061469e828561465a565b6004820191506146ae828461467b565b6020820191508190509392505050565b6000819050919050565b6146d96146d4826130c3565b6146be565b82525050565b60006146eb8286614536565b91506146f7828561467b565b60208201915061470782846146c8565b602082019150819050949350505050565b600081519050614727816130cd565b92915050565b60006020828403121561474357614742612ec7565b5b600061475184828501614718565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614794826130c3565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036147c6576147c561475a565b5b600182019050919050565b60006147ec6147e76147e284613669565b613762565b6130c3565b9050919050565b6147fc816147d1565b82525050565b600060608201905061481760008301866147f3565b6148246020830185613822565b6148316040830184613822565b949350505050565b600082825260208201905092915050565b7f5f726567697374727920697320656d7074790000000000000000000000000000600082015250565b6000614880601283614839565b915061488b8261484a565b602082019050919050565b600060208201905081810360008301526148af81614873565b9050919050565b7f554d420000000000000000000000000000000000000000000000000000000000815250565b60006020820190506148f0600083016148b6565b919050565b7f5374616b696e6742616e6b000000000000000000000000000000000000000000815250565b600060208201905061492f600083016148f5565b919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600061496a602083614839565b915061497582614934565b602082019050919050565b600060208201905081810360008301526149998161495d565b9050919050565b60006149ab82613669565b91506149b683613669565b9250828210156149c9576149c861475a565b5b828203905092915050565b60006149df826130c3565b91506149ea836130c3565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115614a1f57614a1e61475a565b5b828201905092915050565b6000614a368285614536565b9150614a42828461467b565b6020820191508190509392505050565b614a5b816139dc565b82525050565b6000608082019050614a766000830187613099565b614a836020830186614a52565b614a906040830185613099565b614a9d6060830184613099565b95945050505050565b614aaf816132a8565b8114614aba57600080fd5b50565b600081519050614acc81614aa6565b92915050565b600060208284031215614ae857614ae7612ec7565b5b6000614af684828501614abd565b91505092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000614b5b602683614839565b9150614b6682614aff565b604082019050919050565b60006020820190508181036000830152614b8a81614b4e565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b614bc681614b91565b82525050565b6000602082019050614be16000830184614bbd565b92915050565b6000614bf38284614536565b915081905092915050565b600081519050614c0d816138c1565b92915050565b600060208284031215614c2957614c28612ec7565b5b6000614c3784828501614bfe565b91505092915050565b6000614c4b82613669565b9150614c5683613669565b92508263ffffffff03821115614c6f57614c6e61475a565b5b828201905092915050565b600080fd5b600060a08284031215614c9557614c94614c7a565b5b614c9f60a0612f4c565b90506000614caf84828501614bfe565b6000830152506020614cc384828501614bfe565b6020830152506040614cd784828501614bfe565b6040830152506060614ceb84828501614bfe565b6060830152506080614cff84828501614abd565b60808301525092915050565b600060a08284031215614d2157614d20612ec7565b5b6000614d2f84828501614c7f565b91505092915050565b6000614d43826143c1565b9150614d4e836143c1565b925082821015614d6157614d6061475a565b5b828203905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614da6826143c1565b9150614db1836143c1565b925082614dc157614dc0614d6c565b5b82820490509291505056fea2646970667358221220c360ae03d3a676b33b3c5097d3c8e8893865decc08d54266712bbb98da90469d64736f6c634300080d0033", diff --git a/deployments/arbitrum_production/StakingBankStatic.json b/deployments/arbitrum_production/StakingBankStatic.json index ec2493e3..c1c2d09c 100644 --- a/deployments/arbitrum_production/StakingBankStatic.json +++ b/deployments/arbitrum_production/StakingBankStatic.json @@ -1,5 +1,5 @@ { - "address": "0x6a7ED15b7F557A2c8189B0d8149D6FeBAc1969Be", + "address": "0x846F52020749715F02AEf25b5d1d65e48945649D", "abi": [ { "inputs": [ @@ -249,58 +249,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "VALIDATOR_15", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATOR_16", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATOR_17", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATOR_18", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "VALIDATOR_2", @@ -812,30 +760,30 @@ "type": "function" } ], - "transactionHash": "0x4bf7f9fee5d99a0cf7357246053ad56cdece932bac2865ff656faf45bab5a5d4", + "transactionHash": "0x00d727e13187d1ee53214b505d21189edbdce42995d0fc1adcc2d6c9d8750e7a", "receipt": { "to": null, "from": "0xA6e4fFa19B213AbeA258ae72e8e1a209B9E543e7", - "contractAddress": "0x6a7ED15b7F557A2c8189B0d8149D6FeBAc1969Be", - "transactionIndex": 2, - "gasUsed": "16375017", + "contractAddress": "0x846F52020749715F02AEf25b5d1d65e48945649D", + "transactionIndex": 3, + "gasUsed": "5171678", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x443e0be6f1971e3bfa84bea08b36ead58ddf4a71abd30f50963bcefe9365e1e1", - "transactionHash": "0x4bf7f9fee5d99a0cf7357246053ad56cdece932bac2865ff656faf45bab5a5d4", + "blockHash": "0xea9cd57766c923171517df82c0a24b6043cddda3a5e9aae066fb16ee0a77409e", + "transactionHash": "0x00d727e13187d1ee53214b505d21189edbdce42995d0fc1adcc2d6c9d8750e7a", "logs": [], - "blockNumber": 147982584, - "cumulativeGasUsed": "17304354", + "blockNumber": 269195342, + "cumulativeGasUsed": "6767910", "status": 1, "byzantium": true }, "args": [ - 19 + 15 ], - "numDeployments": 3, - "solcInputHash": "4db3e1d3dd51dbe508dc0a6a04352df6", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_validatorsCount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"NotSupported\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"minAmountForStake\",\"type\":\"uint256\"}],\"name\":\"LogMinAmountForStake\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"NUMBER_OF_VALIDATORS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ONE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TOTAL_SUPPLY\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_0\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_1\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_10\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_11\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_12\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_13\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_14\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_15\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_16\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_17\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_18\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_2\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_3\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_4\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_5\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_6\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_7\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_8\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_9\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_ix\",\"type\":\"uint256\"}],\"name\":\"addresses\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validator\",\"type\":\"address\"}],\"name\":\"balances\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"create\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"exit\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBalances\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"allBalances\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumberOfValidators\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"receiveApproval\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"register\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"remove\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"setMinAmountForStake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"stake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"update\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_id\",\"type\":\"address\"}],\"name\":\"validators\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"location\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_validators\",\"type\":\"address[]\"}],\"name\":\"verifyValidators\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addresses(uint256)\":{\"details\":\"gets validator address for provided index\",\"params\":{\"_ix\":\"index in array of list of all validators wallets\"}},\"balanceOf(address)\":{\"details\":\"to follow ERC20 interface\"},\"exit()\":{\"details\":\"unstake and withdraw all tokens\"},\"getName()\":{\"details\":\"to follow Registrable interface\"},\"getNumberOfValidators()\":{\"returns\":{\"_0\":\"total number of registered validators (with and without balance)\"}},\"register()\":{\"details\":\"to follow Registrable interface\"},\"totalSupply()\":{\"details\":\"to follow ERC20 interface\"},\"unregister()\":{\"details\":\"to follow Registrable interface\"},\"validators(address)\":{\"params\":{\"_id\":\"address of validator\"},\"returns\":{\"id\":\"address of validator\",\"location\":\"URL of validator\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":\"StakingBankStaticProd\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":0},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBank.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IStakingBank is IERC20 {\\n /// @param id address of validator wallet\\n /// @param location URL of the validator API\\n struct Validator {\\n address id;\\n string location;\\n }\\n\\n event LogValidatorRegistered(address indexed id);\\n event LogValidatorUpdated(address indexed id);\\n event LogValidatorRemoved(address indexed id);\\n event LogMinAmountForStake(uint256 minAmountForStake);\\n\\n /// @dev setter for `minAmountForStake`\\n function setMinAmountForStake(uint256 _minAmountForStake) external;\\n\\n /// @dev allows to stake `token` by validators\\n /// Validator needs to approve StakingBank beforehand\\n /// @param _value amount of tokens to stake\\n function stake(uint256 _value) external;\\n\\n /// @dev notification about approval from `_from` address on UMB token\\n /// Staking bank will stake max approved amount from `_from` address\\n /// @param _from address which approved token spend for IStakingBank\\n function receiveApproval(address _from) external returns (bool success);\\n\\n /// @dev withdraws stake tokens\\n /// it throws, when balance will be less than required minimum for stake\\n /// to withdraw all use `exit`\\n function withdraw(uint256 _value) external returns (bool success);\\n\\n /// @dev unstake and withdraw all tokens\\n function exit() external returns (bool success);\\n\\n /// @dev creates (register) new validator\\n /// @param _id validator address\\n /// @param _location location URL of the validator API\\n function create(address _id, string calldata _location) external;\\n\\n /// @dev removes validator\\n /// @param _id validator wallet\\n function remove(address _id) external;\\n\\n /// @dev updates validator location\\n /// @param _id validator wallet\\n /// @param _location new validator URL\\n function update(address _id, string calldata _location) external;\\n\\n /// @return total number of registered validators (with and without balance)\\n function getNumberOfValidators() external view returns (uint256);\\n\\n /// @dev gets validator address for provided index\\n /// @param _ix index in array of list of all validators wallets\\n function addresses(uint256 _ix) external view returns (address);\\n\\n /// @param _id address of validator\\n /// @return id address of validator\\n /// @return location URL of validator\\n function validators(address _id) external view returns (address id, string memory location);\\n}\\n\",\"keccak256\":\"0x2c518aeab8b0b3a364fafaec559d3ff0dc6a119f8d203fa31ef7ad667ca0f7b9\",\"license\":\"MIT\"},\"contracts/interfaces/StakingBankStaticNotSupported.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./IStakingBank.sol\\\";\\n\\nabstract contract StakingBankStaticNotSupported is IStakingBank {\\n error NotSupported();\\n\\n function create(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function update(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function remove(address) external pure {\\n revert NotSupported();\\n }\\n\\n function transfer(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function transferFrom(address, address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function receiveApproval(address) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function allowance(address, address) external pure returns (uint256) {\\n revert NotSupported();\\n }\\n\\n function approve(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function stake(uint256) external pure {\\n revert NotSupported();\\n }\\n\\n function withdraw(uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function exit() external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function setMinAmountForStake(uint256) external pure {\\n revert NotSupported();\\n }\\n}\\n\",\"keccak256\":\"0xa899ad9000220b04bc3f63f762a9a6a76dcc09449427e7774a53f4ceda9c1cf8\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStatic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"../interfaces/StakingBankStaticNotSupported.sol\\\";\\n\\n/// @dev Because we are using PoA in UMB oracle, staked balance does not matter. What's matter is, if signer is\\n/// validator or not. In this case we can optimise `StakingBank` and make it static for better gas performance.\\nabstract contract StakingBankStatic is StakingBankStaticNotSupported {\\n uint256 public constant ONE = 1e18;\\n\\n uint256 public immutable NUMBER_OF_VALIDATORS; // solhint-disable-line var-name-mixedcase\\n uint256 public immutable TOTAL_SUPPLY; // solhint-disable-line var-name-mixedcase\\n\\n constructor(uint256 _validatorsCount) {\\n NUMBER_OF_VALIDATORS = _validatorsCount;\\n TOTAL_SUPPLY = _validatorsCount * ONE;\\n\\n _assertValidSetup(_validatorsCount);\\n }\\n\\n function balances(address _validator) external view returns (uint256) {\\n return _isValidator(_validator) ? ONE : 0;\\n }\\n\\n function verifyValidators(address[] calldata _validators) external view returns (bool) {\\n for (uint256 i; i < _validators.length;) {\\n if (!_isValidator(_validators[i])) return false;\\n unchecked { i++; }\\n }\\n\\n return true;\\n }\\n\\n function getNumberOfValidators() external view returns (uint256) {\\n return NUMBER_OF_VALIDATORS;\\n }\\n\\n function getAddresses() external view returns (address[] memory) {\\n return _addresses();\\n }\\n\\n function getBalances() external view returns (uint256[] memory allBalances) {\\n allBalances = new uint256[](NUMBER_OF_VALIDATORS);\\n\\n for (uint256 i; i < NUMBER_OF_VALIDATORS;) {\\n allBalances[i] = ONE;\\n\\n unchecked {\\n // we will not have enough data to overflow\\n i++;\\n }\\n }\\n }\\n\\n function addresses(uint256 _ix) external view returns (address) {\\n return _addresses()[_ix];\\n }\\n\\n function validators(address _id) external view virtual returns (address id, string memory location);\\n\\n /// @dev to follow ERC20 interface\\n function balanceOf(address _account) external view returns (uint256) {\\n return _isValidator(_account) ? ONE : 0;\\n }\\n\\n /// @dev to follow ERC20 interface\\n function totalSupply() external view returns (uint256) {\\n return TOTAL_SUPPLY;\\n }\\n\\n /// @dev to follow Registrable interface\\n function getName() external pure returns (bytes32) {\\n return \\\"StakingBank\\\";\\n }\\n\\n /// @dev to follow Registrable interface\\n function register() external pure {\\n // there are no requirements atm\\n }\\n\\n /// @dev to follow Registrable interface\\n function unregister() external pure {\\n // there are no requirements atm\\n }\\n\\n function _addresses() internal view virtual returns (address[] memory);\\n\\n function _isValidator(address _validator) internal view virtual returns (bool);\\n\\n function _assertValidSetup(uint256 _validatorsCount) internal view virtual{\\n address[] memory list = _addresses();\\n require(list.length == _validatorsCount);\\n\\n for (uint256 i; i < _validatorsCount;) {\\n require(_isValidator(list[i]));\\n\\n unchecked { i ++; }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfcc53ff98b0f1c42e1bc7345a1535fdc4e938ef40d323600ead94b2ece59a381\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./StakingBankStatic.sol\\\";\\n\\ncontract StakingBankStaticProd is StakingBankStatic {\\n address public constant VALIDATOR_0 = 0x977Ba523420110e230643B772Fe9cF955e11dA7B;\\n address public constant VALIDATOR_1 = 0xe2422b23e52bc13ebA04d7FbB9F332Deb43360fB;\\n\\n // external order is based on validators submits on AVAX for Apr 2023\\n address public constant VALIDATOR_2 = 0x57F404aD75e371c1A539589C1eFCA12e0C6980AD;\\n address public constant VALIDATOR_3 = 0xD56C6A4f64E0bD70260472d1DB6Cf5825858CB0d;\\n address public constant VALIDATOR_4 = 0x220230Eda8f50067Dd9e4729345dabCCe0C61542;\\n address public constant VALIDATOR_5 = 0x93FdcAB283b0BcAc48157590af482E1CFd6af6aC;\\n address public constant VALIDATOR_6 = 0xCd733E06B06083d52fC5867E8E3432aA5c103A38;\\n address public constant VALIDATOR_7 = 0x42e210b110c6aa49CdfA7ceF1444Aa4719653111;\\n address public constant VALIDATOR_8 = 0x501731c6a69803a53Ec6c3e12f293c247cE1092B;\\n address public constant VALIDATOR_9 = 0x8bF9661F1b247522C75DD0FE84355aD2EfF27144;\\n address public constant VALIDATOR_10 = 0x281754Ab58391A478B7aA4E7f39991CfB41118c4;\\n address public constant VALIDATOR_11 = 0xB9C63a350A04d8BD245d18928a26EE036352dDd8;\\n address public constant VALIDATOR_12 = 0x57A51D5BDcE188c2295fCA3b4687475a54E65A02;\\n address public constant VALIDATOR_13 = 0x777FbA3666fa7747476a34577FcCC404b263E09F;\\n address public constant VALIDATOR_14 = 0x2F85824B2B38F179E451988670935d315b5b9692;\\n address public constant VALIDATOR_15 = 0xA7241994267682de4dE7Ef62f52dc2C783d1784B;\\n address public constant VALIDATOR_16 = 0x6eEd457C20603EDAE50C3A112CAA1a9425321bD0;\\n address public constant VALIDATOR_17 = 0xC5a7650c2725a7B6A39f15cb9FbffC7af357AFeb;\\n address public constant VALIDATOR_18 = 0xFEd95453678920c1b7b3A81F033Ca02a27225556;\\n\\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\\n\\n // solhint-disable-next-line code-complexity\\n function validators(address _id) external pure override returns (address id, string memory location) {\\n if (_id == VALIDATOR_0) return (_id, \\\"https://validator.umb.network\\\");\\n if (_id == VALIDATOR_1) return (_id, \\\"https://validator2.umb.network\\\");\\n if (_id == VALIDATOR_2) return (_id, \\\"https://umbrella.artemahr.tech\\\");\\n if (_id == VALIDATOR_3) return (_id, \\\"https://umb.vtabsolutions.com:3030\\\");\\n if (_id == VALIDATOR_4) return (_id, \\\"https://umb.stakers.world\\\");\\n if (_id == VALIDATOR_5) return (_id, \\\"https://umbrella.crazywhale.es\\\");\\n if (_id == VALIDATOR_6) return (_id, \\\"https://umbrella-node.gateomega.com\\\");\\n if (_id == VALIDATOR_7) return (_id, \\\"https://umb.anorak.technology\\\");\\n if (_id == VALIDATOR_8) return (_id, \\\"https://umbrella.validator.infstones.io\\\");\\n if (_id == VALIDATOR_9) return (_id, \\\"https://umb.hashquark.io\\\");\\n if (_id == VALIDATOR_10) return (_id, \\\"http://umbrella.staking4all.org:3000\\\");\\n if (_id == VALIDATOR_11) return (_id, \\\"https://umbrella-api.validatrium.club\\\");\\n if (_id == VALIDATOR_12) return (_id, \\\"http://5.161.78.230:3000\\\");\\n if (_id == VALIDATOR_13) return (_id, \\\"https://umbnode.blockchainliverpool.com\\\");\\n if (_id == VALIDATOR_14) return (_id, \\\"https://umb-api.staking.rocks\\\");\\n if (_id == VALIDATOR_15) return (_id, \\\"https://rpc.urbanhq.net\\\");\\n if (_id == VALIDATOR_16) return (_id, \\\"https://umbrella-node.ankastake.com\\\");\\n if (_id == VALIDATOR_17) return (_id, \\\"https://umbrella.tchambrella.com\\\");\\n if (_id == VALIDATOR_18) return (_id, \\\"https://umbrella-node.cmt13.eu\\\");\\n\\n return (address(0), \\\"\\\");\\n }\\n\\n function _addresses() internal view override returns (address[] memory) {\\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\\n\\n list[0] = VALIDATOR_0;\\n list[1] = VALIDATOR_1;\\n list[2] = VALIDATOR_2;\\n list[3] = VALIDATOR_3;\\n list[4] = VALIDATOR_4;\\n list[5] = VALIDATOR_5;\\n list[6] = VALIDATOR_6;\\n list[7] = VALIDATOR_7;\\n list[8] = VALIDATOR_8;\\n list[9] = VALIDATOR_9;\\n list[10] = VALIDATOR_10;\\n list[11] = VALIDATOR_11;\\n list[12] = VALIDATOR_12;\\n list[13] = VALIDATOR_13;\\n list[14] = VALIDATOR_14;\\n list[15] = VALIDATOR_15;\\n list[16] = VALIDATOR_16;\\n list[17] = VALIDATOR_17;\\n list[18] = VALIDATOR_18;\\n\\n return list;\\n }\\n\\n function _isValidator(address _validator) internal pure override returns (bool) {\\n return (\\n _validator == VALIDATOR_0\\n || _validator == VALIDATOR_1\\n || _validator == VALIDATOR_2\\n || _validator == VALIDATOR_3\\n || _validator == VALIDATOR_4\\n || _validator == VALIDATOR_5\\n || _validator == VALIDATOR_6\\n || _validator == VALIDATOR_7\\n || _validator == VALIDATOR_8\\n || _validator == VALIDATOR_9\\n || _validator == VALIDATOR_10\\n || _validator == VALIDATOR_11\\n || _validator == VALIDATOR_12\\n || _validator == VALIDATOR_13\\n || _validator == VALIDATOR_14\\n || _validator == VALIDATOR_15\\n || _validator == VALIDATOR_16\\n || _validator == VALIDATOR_17\\n || _validator == VALIDATOR_18\\n );\\n }\\n}\\n\",\"keccak256\":\"0x1e80a063f381fdb75109238bd1e4db75af37b5aea8d8165293aee4bf84838c85\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60c06040523480156200001157600080fd5b5060405162003da238038062003da2833981810160405281019062000037919062000eaf565b808060808181525050670de0b6b3a76400008162000056919062000f10565b60a081815250506200006e816200007660201b60201c565b505062000fcf565b600062000088620000ef60201b60201c565b9050818151146200009857600080fd5b60005b82811015620000ea57620000d2828281518110620000be57620000bd62000f71565b5b6020026020010151620008dd60201b60201c565b620000dc57600080fd5b80806001019150506200009b565b505050565b6060600060805167ffffffffffffffff81111562000112576200011162000fa0565b5b604051908082528060200260200182016040528015620001415781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b8160008151811062000170576200016f62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110620001d657620001d562000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad816002815181106200023c576200023b62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110620002a257620002a162000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073220230eda8f50067dd9e4729345dabcce0c615428160048151811062000308576200030762000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac816005815181106200036e576200036d62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a3881600681518110620003d457620003d362000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa4719653111816007815181106200043a576200043962000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b81600881518110620004a0576200049f62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff271448160098151811062000506576200050562000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600a815181106200056c576200056b62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073b9c63a350a04d8bd245d18928a26ee036352ddd881600b81518110620005d257620005d162000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600c8151811062000638576200063762000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073777fba3666fa7747476a34577fccc404b263e09f81600d815181106200069e576200069d62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600e8151811062000704576200070362000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600f815181106200076a576200076962000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081601081518110620007d057620007cf62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb8160118151811062000836576200083562000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073fed95453678920c1b7b3a81f033ca02a27225556816012815181106200089c576200089b62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806200096d575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80620009b857507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a03575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a4e575073220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a9957507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ae4575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b2f57507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b7a575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000bc55750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000c10575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000c5b575073b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ca657507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000cf1575073777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000d3c5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000d87575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000dd25750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000e1d575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000e68575073fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b600080fd5b6000819050919050565b62000e898162000e74565b811462000e9557600080fd5b50565b60008151905062000ea98162000e7e565b92915050565b60006020828403121562000ec85762000ec762000e6f565b5b600062000ed88482850162000e98565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600062000f1d8262000e74565b915062000f2a8362000e74565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161562000f665762000f6562000ee1565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60805160a051612d8a62001018600039600081816109ac0152610c2e01526000818161081b0152818161088901528181610c5401528181610dbd0152611db40152612d8a6000f3fe608060405234801561001057600080fd5b50600436106102195760003560e01c8062113e081461021e578063015f7ed61461023c57806303a1e2241461025a578063095ea7b3146102785780630db18e37146102a857806317d7de7c146102d857806318160ddd146102f65780631aa3a008146103145780631d4f9ce01461031e57806323b872dd1461034e57806327e235e31461037e57806329092d0e146103ae5780632e1a7d4d146103ca578063398b056e146103fa578063411ff4971461041857806345f9f8251461043657806352b41e351461045457806354755335146104705780635dc4bfd31461048e57806361a3e37e146104ac57806369dc7ae4146104ca57806370a08231146104e8578063838e7c3a14610518578063902d55a5146105345780639031d9131461055257806390ff7e2e14610570578063952c4f181461058e578063989b6996146105ac5780639f0e9484146105ca578063a15ab08d146105e8578063a39fac1214610604578063a694fc3a14610622578063a9059cbb1461063e578063b2119eac1461066e578063b49b08421461068c578063c2ee3a08146106aa578063db731777146106c8578063dd62ed3e146106e6578063e214a5fc14610716578063e29349d614610734578063e2dc7a1a14610752578063e79a198f14610770578063e985e0081461077a578063e9fad8ee14610798578063edf26d9b146107b6578063fa52c7d8146107e6575b600080fd5b610226610817565b6040516102339190612645565b60405180910390f35b6102446108e8565b60405161025191906126a8565b60405180910390f35b610262610900565b60405161026f91906126a8565b60405180910390f35b610292600480360381019061028d9190612725565b610918565b60405161029f9190612780565b60405180910390f35b6102c260048036038101906102bd919061279b565b61094c565b6040516102cf9190612780565b60405180910390f35b6102e0610980565b6040516102ed91906127e1565b60405180910390f35b6102fe6109a8565b60405161030b919061280b565b60405180910390f35b61031c6109d0565b005b6103386004803603810190610333919061288b565b6109d2565b6040516103459190612780565b60405180910390f35b610368600480360381019061036391906128d8565b610a38565b6040516103759190612780565b60405180910390f35b6103986004803603810190610393919061279b565b610a6c565b6040516103a5919061280b565b60405180910390f35b6103c860048036038101906103c3919061279b565b610a93565b005b6103e460048036038101906103df919061292b565b610ac5565b6040516103f19190612780565b60405180910390f35b610402610af9565b60405161040f91906126a8565b60405180910390f35b610420610b11565b60405161042d91906126a8565b60405180910390f35b61043e610b29565b60405161044b91906126a8565b60405180910390f35b61046e6004803603810190610469919061292b565b610b41565b005b610478610b73565b60405161048591906126a8565b60405180910390f35b610496610b8b565b6040516104a391906126a8565b60405180910390f35b6104b4610ba3565b6040516104c191906126a8565b60405180910390f35b6104d2610bbb565b6040516104df91906126a8565b60405180910390f35b61050260048036038101906104fd919061279b565b610bd3565b60405161050f919061280b565b60405180910390f35b610532600480360381019061052d91906129ae565b610bfa565b005b61053c610c2c565b604051610549919061280b565b60405180910390f35b61055a610c50565b604051610567919061280b565b60405180910390f35b610578610c78565b60405161058591906126a8565b60405180910390f35b610596610c90565b6040516105a391906126a8565b60405180910390f35b6105b4610ca8565b6040516105c191906126a8565b60405180910390f35b6105d2610cc0565b6040516105df91906126a8565b60405180910390f35b61060260048036038101906105fd91906129ae565b610cd8565b005b61060c610d0a565b6040516106199190612acc565b60405180910390f35b61063c6004803603810190610637919061292b565b610d19565b005b61065860048036038101906106539190612725565b610d4b565b6040516106659190612780565b60405180910390f35b610676610d7f565b60405161068391906126a8565b60405180910390f35b610694610d97565b6040516106a191906126a8565b60405180910390f35b6106b2610daf565b6040516106bf919061280b565b60405180910390f35b6106d0610dbb565b6040516106dd919061280b565b60405180910390f35b61070060048036038101906106fb9190612aee565b610ddf565b60405161070d919061280b565b60405180910390f35b61071e610e13565b60405161072b91906126a8565b60405180910390f35b61073c610e2b565b60405161074991906126a8565b60405180910390f35b61075a610e43565b60405161076791906126a8565b60405180910390f35b610778610e5b565b005b610782610e5d565b60405161078f91906126a8565b60405180910390f35b6107a0610e75565b6040516107ad9190612780565b60405180910390f35b6107d060048036038101906107cb919061292b565b610ea9565b6040516107dd91906126a8565b60405180910390f35b61080060048036038101906107fb919061279b565b610ed4565b60405161080e929190612bc7565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff81111561085357610852612bf7565b5b6040519080825280602002602001820160405280156108815781602001602082028036833780820191505090505b50905060005b7f00000000000000000000000000000000000000000000000000000000000000008110156108e457670de0b6b3a76400008282815181106108cb576108ca612c26565b5b6020026020010181815250508080600101915050610887565b5090565b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b83839050811015610a2c57610a118484838181106109f7576109f6612c26565b5b9050602002016020810190610a0c919061279b565b61182e565b610a1f576000915050610a32565b80806001019150506109d6565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a778261182e565b610a82576000610a8c565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b732f85824b2b38f179e451988670935d315b5b969281565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b73fed95453678920c1b7b3a81f033ca02a2722555681565b73777fba3666fa7747476a34577fccc404b263e09f81565b6000610bde8261182e565b610be9576000610bf3565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b73220230eda8f50067dd9e4729345dabcce0c6154281565b73a7241994267682de4de7ef62f52dc2c783d1784b81565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610d14611dae565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73281754ab58391a478b7aa4e7f39991cfb41118c481565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b736eed457c20603edae50c3a112caa1a9425321bd081565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b565b73b9c63a350a04d8bd245d18928a26ee036352ddd881565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610eb3611dae565b8281518110610ec557610ec4612c26565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f5f57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611829565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fe657826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611829565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361106d57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611829565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110d75782604051806060016040528060228152602001612c796022913991509150611829565b73220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361115e57826040518060400160405280601981526020017f68747470733a2f2f756d622e7374616b6572732e776f726c640000000000000081525091509150611829565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111e557826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611829565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361124f5782604051806060016040528060238152602001612c566023913991509150611829565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112d657826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611829565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113405782604051806060016040528060278152602001612cbf6027913991509150611829565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113c757826040518060400160405280601881526020017f68747470733a2f2f756d622e68617368717561726b2e696f000000000000000081525091509150611829565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114315782604051806060016040528060248152602001612c9b6024913991509150611829565b73b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361149b5782604051806060016040528060258152602001612ce66025913991509150611829565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152257826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611829565b73777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361158c5782604051806060016040528060278152602001612d2e6027913991509150611829565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361161357826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611829565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361169a57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611829565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036117045782604051806060016040528060238152602001612d0b6023913991509150611829565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361178b57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611829565b73fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361181257826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612d6e6f64652e636d7431332e6575000081525091509150611829565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806118bd575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061190757507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611951575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061199b575073220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806119e557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a2f575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a7957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ac3575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b0d5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b57575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ba1575073b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611beb57507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c35575073777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c7f5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611cc9575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d135750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d5d575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611da7575073fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff811115611dec57611deb612bf7565b5b604051908082528060200260200182016040528015611e1a5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611e4657611e45612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611ea957611ea8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611f0c57611f0b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611f6f57611f6e612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073220230eda8f50067dd9e4729345dabcce0c6154281600481518110611fd257611fd1612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac8160058151811061203557612034612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a388160068151811061209857612097612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa4719653111816007815181106120fb576120fa612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b8160088151811061215e5761215d612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff27144816009815181106121c1576121c0612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600a8151811061222457612223612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073b9c63a350a04d8bd245d18928a26ee036352ddd881600b8151811061228757612286612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600c815181106122ea576122e9612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073777fba3666fa7747476a34577fccc404b263e09f81600d8151811061234d5761234c612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600e815181106123b0576123af612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600f8151811061241357612412612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd08160108151811061247657612475612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb816011815181106124d9576124d8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073fed95453678920c1b7b3a81f033ca02a272255568160128151811061253c5761253b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6125bc816125a9565b82525050565b60006125ce83836125b3565b60208301905092915050565b6000602082019050919050565b60006125f28261257d565b6125fc8185612588565b935061260783612599565b8060005b8381101561263857815161261f88826125c2565b975061262a836125da565b92505060018101905061260b565b5085935050505092915050565b6000602082019050818103600083015261265f81846125e7565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061269282612667565b9050919050565b6126a281612687565b82525050565b60006020820190506126bd6000830184612699565b92915050565b600080fd5b600080fd5b6126d681612687565b81146126e157600080fd5b50565b6000813590506126f3816126cd565b92915050565b612702816125a9565b811461270d57600080fd5b50565b60008135905061271f816126f9565b92915050565b6000806040838503121561273c5761273b6126c3565b5b600061274a858286016126e4565b925050602061275b85828601612710565b9150509250929050565b60008115159050919050565b61277a81612765565b82525050565b60006020820190506127956000830184612771565b92915050565b6000602082840312156127b1576127b06126c3565b5b60006127bf848285016126e4565b91505092915050565b6000819050919050565b6127db816127c8565b82525050565b60006020820190506127f660008301846127d2565b92915050565b612805816125a9565b82525050565b600060208201905061282060008301846127fc565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261284b5761284a612826565b5b8235905067ffffffffffffffff8111156128685761286761282b565b5b60208301915083602082028301111561288457612883612830565b5b9250929050565b600080602083850312156128a2576128a16126c3565b5b600083013567ffffffffffffffff8111156128c0576128bf6126c8565b5b6128cc85828601612835565b92509250509250929050565b6000806000606084860312156128f1576128f06126c3565b5b60006128ff868287016126e4565b9350506020612910868287016126e4565b925050604061292186828701612710565b9150509250925092565b600060208284031215612941576129406126c3565b5b600061294f84828501612710565b91505092915050565b60008083601f84011261296e5761296d612826565b5b8235905067ffffffffffffffff81111561298b5761298a61282b565b5b6020830191508360018202830111156129a7576129a6612830565b5b9250929050565b6000806000604084860312156129c7576129c66126c3565b5b60006129d5868287016126e4565b935050602084013567ffffffffffffffff8111156129f6576129f56126c8565b5b612a0286828701612958565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b612a4381612687565b82525050565b6000612a558383612a3a565b60208301905092915050565b6000602082019050919050565b6000612a7982612a0e565b612a838185612a19565b9350612a8e83612a2a565b8060005b83811015612abf578151612aa68882612a49565b9750612ab183612a61565b925050600181019050612a92565b5085935050505092915050565b60006020820190508181036000830152612ae68184612a6e565b905092915050565b60008060408385031215612b0557612b046126c3565b5b6000612b13858286016126e4565b9250506020612b24858286016126e4565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612b68578082015181840152602081019050612b4d565b83811115612b77576000848401525b50505050565b6000601f19601f8301169050919050565b6000612b9982612b2e565b612ba38185612b39565b9350612bb3818560208601612b4a565b612bbc81612b7d565b840191505092915050565b6000604082019050612bdc6000830185612699565b8181036020830152612bee8184612b8e565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6170692e76616c696461747269756d2e636c756268747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6d68747470733a2f2f756d626e6f64652e626c6f636b636861696e6c69766572706f6f6c2e636f6da26469706673582212209a1752a9ea487818b8a4d658f151da9487c0cc92638142159bacde7ec2d21f7564736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102195760003560e01c8062113e081461021e578063015f7ed61461023c57806303a1e2241461025a578063095ea7b3146102785780630db18e37146102a857806317d7de7c146102d857806318160ddd146102f65780631aa3a008146103145780631d4f9ce01461031e57806323b872dd1461034e57806327e235e31461037e57806329092d0e146103ae5780632e1a7d4d146103ca578063398b056e146103fa578063411ff4971461041857806345f9f8251461043657806352b41e351461045457806354755335146104705780635dc4bfd31461048e57806361a3e37e146104ac57806369dc7ae4146104ca57806370a08231146104e8578063838e7c3a14610518578063902d55a5146105345780639031d9131461055257806390ff7e2e14610570578063952c4f181461058e578063989b6996146105ac5780639f0e9484146105ca578063a15ab08d146105e8578063a39fac1214610604578063a694fc3a14610622578063a9059cbb1461063e578063b2119eac1461066e578063b49b08421461068c578063c2ee3a08146106aa578063db731777146106c8578063dd62ed3e146106e6578063e214a5fc14610716578063e29349d614610734578063e2dc7a1a14610752578063e79a198f14610770578063e985e0081461077a578063e9fad8ee14610798578063edf26d9b146107b6578063fa52c7d8146107e6575b600080fd5b610226610817565b6040516102339190612645565b60405180910390f35b6102446108e8565b60405161025191906126a8565b60405180910390f35b610262610900565b60405161026f91906126a8565b60405180910390f35b610292600480360381019061028d9190612725565b610918565b60405161029f9190612780565b60405180910390f35b6102c260048036038101906102bd919061279b565b61094c565b6040516102cf9190612780565b60405180910390f35b6102e0610980565b6040516102ed91906127e1565b60405180910390f35b6102fe6109a8565b60405161030b919061280b565b60405180910390f35b61031c6109d0565b005b6103386004803603810190610333919061288b565b6109d2565b6040516103459190612780565b60405180910390f35b610368600480360381019061036391906128d8565b610a38565b6040516103759190612780565b60405180910390f35b6103986004803603810190610393919061279b565b610a6c565b6040516103a5919061280b565b60405180910390f35b6103c860048036038101906103c3919061279b565b610a93565b005b6103e460048036038101906103df919061292b565b610ac5565b6040516103f19190612780565b60405180910390f35b610402610af9565b60405161040f91906126a8565b60405180910390f35b610420610b11565b60405161042d91906126a8565b60405180910390f35b61043e610b29565b60405161044b91906126a8565b60405180910390f35b61046e6004803603810190610469919061292b565b610b41565b005b610478610b73565b60405161048591906126a8565b60405180910390f35b610496610b8b565b6040516104a391906126a8565b60405180910390f35b6104b4610ba3565b6040516104c191906126a8565b60405180910390f35b6104d2610bbb565b6040516104df91906126a8565b60405180910390f35b61050260048036038101906104fd919061279b565b610bd3565b60405161050f919061280b565b60405180910390f35b610532600480360381019061052d91906129ae565b610bfa565b005b61053c610c2c565b604051610549919061280b565b60405180910390f35b61055a610c50565b604051610567919061280b565b60405180910390f35b610578610c78565b60405161058591906126a8565b60405180910390f35b610596610c90565b6040516105a391906126a8565b60405180910390f35b6105b4610ca8565b6040516105c191906126a8565b60405180910390f35b6105d2610cc0565b6040516105df91906126a8565b60405180910390f35b61060260048036038101906105fd91906129ae565b610cd8565b005b61060c610d0a565b6040516106199190612acc565b60405180910390f35b61063c6004803603810190610637919061292b565b610d19565b005b61065860048036038101906106539190612725565b610d4b565b6040516106659190612780565b60405180910390f35b610676610d7f565b60405161068391906126a8565b60405180910390f35b610694610d97565b6040516106a191906126a8565b60405180910390f35b6106b2610daf565b6040516106bf919061280b565b60405180910390f35b6106d0610dbb565b6040516106dd919061280b565b60405180910390f35b61070060048036038101906106fb9190612aee565b610ddf565b60405161070d919061280b565b60405180910390f35b61071e610e13565b60405161072b91906126a8565b60405180910390f35b61073c610e2b565b60405161074991906126a8565b60405180910390f35b61075a610e43565b60405161076791906126a8565b60405180910390f35b610778610e5b565b005b610782610e5d565b60405161078f91906126a8565b60405180910390f35b6107a0610e75565b6040516107ad9190612780565b60405180910390f35b6107d060048036038101906107cb919061292b565b610ea9565b6040516107dd91906126a8565b60405180910390f35b61080060048036038101906107fb919061279b565b610ed4565b60405161080e929190612bc7565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff81111561085357610852612bf7565b5b6040519080825280602002602001820160405280156108815781602001602082028036833780820191505090505b50905060005b7f00000000000000000000000000000000000000000000000000000000000000008110156108e457670de0b6b3a76400008282815181106108cb576108ca612c26565b5b6020026020010181815250508080600101915050610887565b5090565b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b83839050811015610a2c57610a118484838181106109f7576109f6612c26565b5b9050602002016020810190610a0c919061279b565b61182e565b610a1f576000915050610a32565b80806001019150506109d6565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a778261182e565b610a82576000610a8c565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b732f85824b2b38f179e451988670935d315b5b969281565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b73fed95453678920c1b7b3a81f033ca02a2722555681565b73777fba3666fa7747476a34577fccc404b263e09f81565b6000610bde8261182e565b610be9576000610bf3565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b73220230eda8f50067dd9e4729345dabcce0c6154281565b73a7241994267682de4de7ef62f52dc2c783d1784b81565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610d14611dae565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73281754ab58391a478b7aa4e7f39991cfb41118c481565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b736eed457c20603edae50c3a112caa1a9425321bd081565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b565b73b9c63a350a04d8bd245d18928a26ee036352ddd881565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610eb3611dae565b8281518110610ec557610ec4612c26565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f5f57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611829565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fe657826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611829565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361106d57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611829565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110d75782604051806060016040528060228152602001612c796022913991509150611829565b73220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361115e57826040518060400160405280601981526020017f68747470733a2f2f756d622e7374616b6572732e776f726c640000000000000081525091509150611829565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111e557826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611829565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361124f5782604051806060016040528060238152602001612c566023913991509150611829565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112d657826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611829565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113405782604051806060016040528060278152602001612cbf6027913991509150611829565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113c757826040518060400160405280601881526020017f68747470733a2f2f756d622e68617368717561726b2e696f000000000000000081525091509150611829565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114315782604051806060016040528060248152602001612c9b6024913991509150611829565b73b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361149b5782604051806060016040528060258152602001612ce66025913991509150611829565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152257826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611829565b73777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361158c5782604051806060016040528060278152602001612d2e6027913991509150611829565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361161357826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611829565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361169a57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611829565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036117045782604051806060016040528060238152602001612d0b6023913991509150611829565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361178b57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611829565b73fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361181257826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612d6e6f64652e636d7431332e6575000081525091509150611829565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806118bd575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061190757507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611951575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061199b575073220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806119e557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a2f575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a7957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ac3575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b0d5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b57575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ba1575073b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611beb57507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c35575073777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c7f5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611cc9575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d135750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d5d575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611da7575073fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff811115611dec57611deb612bf7565b5b604051908082528060200260200182016040528015611e1a5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611e4657611e45612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611ea957611ea8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611f0c57611f0b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611f6f57611f6e612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073220230eda8f50067dd9e4729345dabcce0c6154281600481518110611fd257611fd1612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac8160058151811061203557612034612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a388160068151811061209857612097612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa4719653111816007815181106120fb576120fa612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b8160088151811061215e5761215d612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff27144816009815181106121c1576121c0612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600a8151811061222457612223612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073b9c63a350a04d8bd245d18928a26ee036352ddd881600b8151811061228757612286612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600c815181106122ea576122e9612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073777fba3666fa7747476a34577fccc404b263e09f81600d8151811061234d5761234c612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600e815181106123b0576123af612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600f8151811061241357612412612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd08160108151811061247657612475612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb816011815181106124d9576124d8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073fed95453678920c1b7b3a81f033ca02a272255568160128151811061253c5761253b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6125bc816125a9565b82525050565b60006125ce83836125b3565b60208301905092915050565b6000602082019050919050565b60006125f28261257d565b6125fc8185612588565b935061260783612599565b8060005b8381101561263857815161261f88826125c2565b975061262a836125da565b92505060018101905061260b565b5085935050505092915050565b6000602082019050818103600083015261265f81846125e7565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061269282612667565b9050919050565b6126a281612687565b82525050565b60006020820190506126bd6000830184612699565b92915050565b600080fd5b600080fd5b6126d681612687565b81146126e157600080fd5b50565b6000813590506126f3816126cd565b92915050565b612702816125a9565b811461270d57600080fd5b50565b60008135905061271f816126f9565b92915050565b6000806040838503121561273c5761273b6126c3565b5b600061274a858286016126e4565b925050602061275b85828601612710565b9150509250929050565b60008115159050919050565b61277a81612765565b82525050565b60006020820190506127956000830184612771565b92915050565b6000602082840312156127b1576127b06126c3565b5b60006127bf848285016126e4565b91505092915050565b6000819050919050565b6127db816127c8565b82525050565b60006020820190506127f660008301846127d2565b92915050565b612805816125a9565b82525050565b600060208201905061282060008301846127fc565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261284b5761284a612826565b5b8235905067ffffffffffffffff8111156128685761286761282b565b5b60208301915083602082028301111561288457612883612830565b5b9250929050565b600080602083850312156128a2576128a16126c3565b5b600083013567ffffffffffffffff8111156128c0576128bf6126c8565b5b6128cc85828601612835565b92509250509250929050565b6000806000606084860312156128f1576128f06126c3565b5b60006128ff868287016126e4565b9350506020612910868287016126e4565b925050604061292186828701612710565b9150509250925092565b600060208284031215612941576129406126c3565b5b600061294f84828501612710565b91505092915050565b60008083601f84011261296e5761296d612826565b5b8235905067ffffffffffffffff81111561298b5761298a61282b565b5b6020830191508360018202830111156129a7576129a6612830565b5b9250929050565b6000806000604084860312156129c7576129c66126c3565b5b60006129d5868287016126e4565b935050602084013567ffffffffffffffff8111156129f6576129f56126c8565b5b612a0286828701612958565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b612a4381612687565b82525050565b6000612a558383612a3a565b60208301905092915050565b6000602082019050919050565b6000612a7982612a0e565b612a838185612a19565b9350612a8e83612a2a565b8060005b83811015612abf578151612aa68882612a49565b9750612ab183612a61565b925050600181019050612a92565b5085935050505092915050565b60006020820190508181036000830152612ae68184612a6e565b905092915050565b60008060408385031215612b0557612b046126c3565b5b6000612b13858286016126e4565b9250506020612b24858286016126e4565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612b68578082015181840152602081019050612b4d565b83811115612b77576000848401525b50505050565b6000601f19601f8301169050919050565b6000612b9982612b2e565b612ba38185612b39565b9350612bb3818560208601612b4a565b612bbc81612b7d565b840191505092915050565b6000604082019050612bdc6000830185612699565b8181036020830152612bee8184612b8e565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6170692e76616c696461747269756d2e636c756268747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6d68747470733a2f2f756d626e6f64652e626c6f636b636861696e6c69766572706f6f6c2e636f6da26469706673582212209a1752a9ea487818b8a4d658f151da9487c0cc92638142159bacde7ec2d21f7564736f6c634300080d0033", + "numDeployments": 4, + "solcInputHash": "dc68422c0ad35a4fe46d461b096b9383", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_validatorsCount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"NotSupported\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"minAmountForStake\",\"type\":\"uint256\"}],\"name\":\"LogMinAmountForStake\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"NUMBER_OF_VALIDATORS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ONE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TOTAL_SUPPLY\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_0\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_1\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_10\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_11\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_12\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_13\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_14\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_2\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_3\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_4\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_5\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_6\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_7\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_8\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_9\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_ix\",\"type\":\"uint256\"}],\"name\":\"addresses\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validator\",\"type\":\"address\"}],\"name\":\"balances\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"create\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"exit\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBalances\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"allBalances\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumberOfValidators\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"receiveApproval\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"register\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"remove\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"setMinAmountForStake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"stake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"update\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_id\",\"type\":\"address\"}],\"name\":\"validators\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"location\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_validators\",\"type\":\"address[]\"}],\"name\":\"verifyValidators\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addresses(uint256)\":{\"details\":\"gets validator address for provided index\",\"params\":{\"_ix\":\"index in array of list of all validators wallets\"}},\"balanceOf(address)\":{\"details\":\"to follow ERC20 interface\"},\"exit()\":{\"details\":\"unstake and withdraw all tokens\"},\"getName()\":{\"details\":\"to follow Registrable interface\"},\"getNumberOfValidators()\":{\"returns\":{\"_0\":\"total number of registered validators (with and without balance)\"}},\"register()\":{\"details\":\"to follow Registrable interface\"},\"totalSupply()\":{\"details\":\"to follow ERC20 interface\"},\"unregister()\":{\"details\":\"to follow Registrable interface\"},\"validators(address)\":{\"params\":{\"_id\":\"address of validator\"},\"returns\":{\"id\":\"address of validator\",\"location\":\"URL of validator\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":\"StakingBankStaticProd\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":0},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBank.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IStakingBank is IERC20 {\\n /// @param id address of validator wallet\\n /// @param location URL of the validator API\\n struct Validator {\\n address id;\\n string location;\\n }\\n\\n event LogValidatorRegistered(address indexed id);\\n event LogValidatorUpdated(address indexed id);\\n event LogValidatorRemoved(address indexed id);\\n event LogMinAmountForStake(uint256 minAmountForStake);\\n\\n /// @dev setter for `minAmountForStake`\\n function setMinAmountForStake(uint256 _minAmountForStake) external;\\n\\n /// @dev allows to stake `token` by validators\\n /// Validator needs to approve StakingBank beforehand\\n /// @param _value amount of tokens to stake\\n function stake(uint256 _value) external;\\n\\n /// @dev notification about approval from `_from` address on UMB token\\n /// Staking bank will stake max approved amount from `_from` address\\n /// @param _from address which approved token spend for IStakingBank\\n function receiveApproval(address _from) external returns (bool success);\\n\\n /// @dev withdraws stake tokens\\n /// it throws, when balance will be less than required minimum for stake\\n /// to withdraw all use `exit`\\n function withdraw(uint256 _value) external returns (bool success);\\n\\n /// @dev unstake and withdraw all tokens\\n function exit() external returns (bool success);\\n\\n /// @dev creates (register) new validator\\n /// @param _id validator address\\n /// @param _location location URL of the validator API\\n function create(address _id, string calldata _location) external;\\n\\n /// @dev removes validator\\n /// @param _id validator wallet\\n function remove(address _id) external;\\n\\n /// @dev updates validator location\\n /// @param _id validator wallet\\n /// @param _location new validator URL\\n function update(address _id, string calldata _location) external;\\n\\n /// @return total number of registered validators (with and without balance)\\n function getNumberOfValidators() external view returns (uint256);\\n\\n /// @dev gets validator address for provided index\\n /// @param _ix index in array of list of all validators wallets\\n function addresses(uint256 _ix) external view returns (address);\\n\\n /// @param _id address of validator\\n /// @return id address of validator\\n /// @return location URL of validator\\n function validators(address _id) external view returns (address id, string memory location);\\n}\\n\",\"keccak256\":\"0x2c518aeab8b0b3a364fafaec559d3ff0dc6a119f8d203fa31ef7ad667ca0f7b9\",\"license\":\"MIT\"},\"contracts/interfaces/StakingBankStaticNotSupported.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./IStakingBank.sol\\\";\\n\\nabstract contract StakingBankStaticNotSupported is IStakingBank {\\n error NotSupported();\\n\\n function create(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function update(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function remove(address) external pure {\\n revert NotSupported();\\n }\\n\\n function transfer(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function transferFrom(address, address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function receiveApproval(address) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function allowance(address, address) external pure returns (uint256) {\\n revert NotSupported();\\n }\\n\\n function approve(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function stake(uint256) external pure {\\n revert NotSupported();\\n }\\n\\n function withdraw(uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function exit() external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function setMinAmountForStake(uint256) external pure {\\n revert NotSupported();\\n }\\n}\\n\",\"keccak256\":\"0xa899ad9000220b04bc3f63f762a9a6a76dcc09449427e7774a53f4ceda9c1cf8\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStatic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"../interfaces/StakingBankStaticNotSupported.sol\\\";\\n\\n/// @dev Because we are using PoA in UMB oracle, staked balance does not matter. What's matter is, if signer is\\n/// validator or not. In this case we can optimise `StakingBank` and make it static for better gas performance.\\nabstract contract StakingBankStatic is StakingBankStaticNotSupported {\\n uint256 public constant ONE = 1e18;\\n\\n uint256 public immutable NUMBER_OF_VALIDATORS; // solhint-disable-line var-name-mixedcase\\n uint256 public immutable TOTAL_SUPPLY; // solhint-disable-line var-name-mixedcase\\n\\n constructor(uint256 _validatorsCount) {\\n NUMBER_OF_VALIDATORS = _validatorsCount;\\n TOTAL_SUPPLY = _validatorsCount * ONE;\\n\\n _assertValidSetup(_validatorsCount);\\n }\\n\\n function balances(address _validator) external view returns (uint256) {\\n return _isValidator(_validator) ? ONE : 0;\\n }\\n\\n function verifyValidators(address[] calldata _validators) external view returns (bool) {\\n for (uint256 i; i < _validators.length;) {\\n if (!_isValidator(_validators[i])) return false;\\n unchecked { i++; }\\n }\\n\\n return true;\\n }\\n\\n function getNumberOfValidators() external view returns (uint256) {\\n return NUMBER_OF_VALIDATORS;\\n }\\n\\n function getAddresses() external view returns (address[] memory) {\\n return _addresses();\\n }\\n\\n function getBalances() external view returns (uint256[] memory allBalances) {\\n allBalances = new uint256[](NUMBER_OF_VALIDATORS);\\n\\n for (uint256 i; i < NUMBER_OF_VALIDATORS;) {\\n allBalances[i] = ONE;\\n\\n unchecked {\\n // we will not have enough data to overflow\\n i++;\\n }\\n }\\n }\\n\\n function addresses(uint256 _ix) external view returns (address) {\\n return _addresses()[_ix];\\n }\\n\\n function validators(address _id) external view virtual returns (address id, string memory location);\\n\\n /// @dev to follow ERC20 interface\\n function balanceOf(address _account) external view returns (uint256) {\\n return _isValidator(_account) ? ONE : 0;\\n }\\n\\n /// @dev to follow ERC20 interface\\n function totalSupply() external view returns (uint256) {\\n return TOTAL_SUPPLY;\\n }\\n\\n /// @dev to follow Registrable interface\\n function getName() external pure returns (bytes32) {\\n return \\\"StakingBank\\\";\\n }\\n\\n /// @dev to follow Registrable interface\\n function register() external pure {\\n // there are no requirements atm\\n }\\n\\n /// @dev to follow Registrable interface\\n function unregister() external pure {\\n // there are no requirements atm\\n }\\n\\n function _addresses() internal view virtual returns (address[] memory);\\n\\n function _isValidator(address _validator) internal view virtual returns (bool);\\n\\n function _assertValidSetup(uint256 _validatorsCount) internal view virtual{\\n address[] memory list = _addresses();\\n require(list.length == _validatorsCount);\\n\\n for (uint256 i; i < _validatorsCount;) {\\n require(_isValidator(list[i]));\\n\\n unchecked { i ++; }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfcc53ff98b0f1c42e1bc7345a1535fdc4e938ef40d323600ead94b2ece59a381\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./StakingBankStatic.sol\\\";\\n\\ncontract StakingBankStaticProd is StakingBankStatic {\\n address public constant VALIDATOR_0 = 0x977Ba523420110e230643B772Fe9cF955e11dA7B;\\n address public constant VALIDATOR_1 = 0xe2422b23e52bc13ebA04d7FbB9F332Deb43360fB;\\n\\n // external order is based on validators submits on AVAX for Apr 2023\\n address public constant VALIDATOR_2 = 0x57F404aD75e371c1A539589C1eFCA12e0C6980AD;\\n address public constant VALIDATOR_3 = 0xD56C6A4f64E0bD70260472d1DB6Cf5825858CB0d;\\n address public constant VALIDATOR_4 = 0x93FdcAB283b0BcAc48157590af482E1CFd6af6aC;\\n address public constant VALIDATOR_5 = 0xCd733E06B06083d52fC5867E8E3432aA5c103A38;\\n address public constant VALIDATOR_6 = 0x42e210b110c6aa49CdfA7ceF1444Aa4719653111;\\n address public constant VALIDATOR_7 = 0x501731c6a69803a53Ec6c3e12f293c247cE1092B;\\n address public constant VALIDATOR_8 = 0x8bF9661F1b247522C75DD0FE84355aD2EfF27144;\\n address public constant VALIDATOR_9 = 0x281754Ab58391A478B7aA4E7f39991CfB41118c4;\\n address public constant VALIDATOR_10 = 0x57A51D5BDcE188c2295fCA3b4687475a54E65A02;\\n address public constant VALIDATOR_11 = 0x2F85824B2B38F179E451988670935d315b5b9692;\\n address public constant VALIDATOR_12 = 0xA7241994267682de4dE7Ef62f52dc2C783d1784B;\\n address public constant VALIDATOR_13 = 0x6eEd457C20603EDAE50C3A112CAA1a9425321bD0;\\n address public constant VALIDATOR_14 = 0xC5a7650c2725a7B6A39f15cb9FbffC7af357AFeb;\\n\\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\\n\\n // solhint-disable-next-line code-complexity\\n function validators(address _id) external pure override returns (address id, string memory location) {\\n if (_id == VALIDATOR_0) return (_id, \\\"https://validator.umb.network\\\");\\n if (_id == VALIDATOR_1) return (_id, \\\"https://validator2.umb.network\\\");\\n if (_id == VALIDATOR_2) return (_id, \\\"https://umbrella.artemahr.tech\\\");\\n if (_id == VALIDATOR_3) return (_id, \\\"https://umb.vtabsolutions.com:3030\\\");\\n if (_id == VALIDATOR_4) return (_id, \\\"https://umbrella.crazywhale.es\\\");\\n if (_id == VALIDATOR_5) return (_id, \\\"https://umbrella-node.gateomega.com\\\");\\n if (_id == VALIDATOR_6) return (_id, \\\"https://umb.anorak.technology\\\");\\n if (_id == VALIDATOR_7) return (_id, \\\"https://umbrella.validator.infstones.io\\\");\\n if (_id == VALIDATOR_8) return (_id, \\\"https://umb.hashkey.cloud\\\");\\n if (_id == VALIDATOR_9) return (_id, \\\"http://umbrella.staking4all.org:3000\\\");\\n if (_id == VALIDATOR_10) return (_id, \\\"http://5.161.78.230:3000\\\");\\n if (_id == VALIDATOR_11) return (_id, \\\"https://umb-api.staking.rocks\\\");\\n if (_id == VALIDATOR_12) return (_id, \\\"https://rpc.urbanhq.net\\\");\\n if (_id == VALIDATOR_13) return (_id, \\\"https://umbrella-node.ankastake.com\\\");\\n if (_id == VALIDATOR_14) return (_id, \\\"https://umbrella.tchambrella.com\\\");\\n\\n return (address(0), \\\"\\\");\\n }\\n\\n function _addresses() internal view override returns (address[] memory) {\\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\\n\\n list[0] = VALIDATOR_0;\\n list[1] = VALIDATOR_1;\\n list[2] = VALIDATOR_2;\\n list[3] = VALIDATOR_3;\\n list[4] = VALIDATOR_4;\\n list[5] = VALIDATOR_5;\\n list[6] = VALIDATOR_6;\\n list[7] = VALIDATOR_7;\\n list[8] = VALIDATOR_8;\\n list[9] = VALIDATOR_9;\\n list[10] = VALIDATOR_10;\\n list[11] = VALIDATOR_11;\\n list[12] = VALIDATOR_12;\\n list[13] = VALIDATOR_13;\\n list[14] = VALIDATOR_14;\\n\\n return list;\\n }\\n\\n function _isValidator(address _validator) internal pure override returns (bool) {\\n return (\\n _validator == VALIDATOR_0\\n || _validator == VALIDATOR_1\\n || _validator == VALIDATOR_2\\n || _validator == VALIDATOR_3\\n || _validator == VALIDATOR_4\\n || _validator == VALIDATOR_5\\n || _validator == VALIDATOR_6\\n || _validator == VALIDATOR_7\\n || _validator == VALIDATOR_8\\n || _validator == VALIDATOR_9\\n || _validator == VALIDATOR_10\\n || _validator == VALIDATOR_11\\n || _validator == VALIDATOR_12\\n || _validator == VALIDATOR_13\\n || _validator == VALIDATOR_14\\n );\\n }\\n}\\n\",\"keccak256\":\"0xcf8016c7d7325800fb6ac9f7afd34804b738daded6239139b23f894855a4f98b\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c06040523480156200001157600080fd5b50604051620034f8380380620034f8833981810160405281019062000037919062000beb565b808060808181525050670de0b6b3a76400008162000056919062000c4c565b60a081815250506200006e816200007660201b60201c565b505062000d0b565b600062000088620000ef60201b60201c565b9050818151146200009857600080fd5b60005b82811015620000ea57620000d2828281518110620000be57620000bd62000cad565b5b60200260200101516200074560201b60201c565b620000dc57600080fd5b80806001019150506200009b565b505050565b6060600060805167ffffffffffffffff81111562000112576200011162000cdc565b5b604051908082528060200260200182016040528015620001415781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b8160008151811062000170576200016f62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110620001d657620001d562000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad816002815181106200023c576200023b62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110620002a257620002a162000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac8160048151811062000308576200030762000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a38816005815181106200036e576200036d62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa471965311181600681518110620003d457620003d362000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b816007815181106200043a576200043962000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff2714481600881518110620004a0576200049f62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c48160098151811062000506576200050562000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600a815181106200056c576200056b62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600b81518110620005d257620005d162000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600c8151811062000638576200063762000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081600d815181106200069e576200069d62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81600e8151811062000704576200070362000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480620007d5575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806200082057507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806200086b575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80620008b657507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000901575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806200094c57507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000997575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80620009e25750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a2d575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a7857507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ac35750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b0e575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b595750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ba4575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b600080fd5b6000819050919050565b62000bc58162000bb0565b811462000bd157600080fd5b50565b60008151905062000be58162000bba565b92915050565b60006020828403121562000c045762000c0362000bab565b5b600062000c148482850162000bd4565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600062000c598262000bb0565b915062000c668362000bb0565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161562000ca25762000ca162000c1d565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60805160a0516127a462000d54600039600081816109080152610b72015260008181610777015281816107e501528181610b9801528181610ce901526119a601526127a46000f3fe608060405234801561001057600080fd5b50600436106101ed5760003560e01c8062113e08146101f2578063015f7ed61461021057806303a1e2241461022e578063095ea7b31461024c5780630db18e371461027c57806317d7de7c146102ac57806318160ddd146102ca5780631aa3a008146102e85780631d4f9ce0146102f257806323b872dd1461032257806327e235e31461035257806329092d0e146103825780632e1a7d4d1461039e578063398b056e146103ce578063411ff497146103ec57806345f9f8251461040a57806352b41e351461042857806354755335146104445780635dc4bfd31461046257806369dc7ae41461048057806370a082311461049e578063838e7c3a146104ce578063902d55a5146104ea5780639031d9131461050857806390ff7e2e14610526578063989b6996146105445780639f0e948414610562578063a15ab08d14610580578063a39fac121461059c578063a694fc3a146105ba578063a9059cbb146105d6578063b2119eac14610606578063b49b084214610624578063c2ee3a0814610642578063db73177714610660578063dd62ed3e1461067e578063e2dc7a1a146106ae578063e79a198f146106cc578063e985e008146106d6578063e9fad8ee146106f4578063edf26d9b14610712578063fa52c7d814610742575b600080fd5b6101fa610773565b60405161020791906120ab565b60405180910390f35b610218610844565b604051610225919061210e565b60405180910390f35b61023661085c565b604051610243919061210e565b60405180910390f35b6102666004803603810190610261919061218b565b610874565b60405161027391906121e6565b60405180910390f35b61029660048036038101906102919190612201565b6108a8565b6040516102a391906121e6565b60405180910390f35b6102b46108dc565b6040516102c19190612247565b60405180910390f35b6102d2610904565b6040516102df9190612271565b60405180910390f35b6102f061092c565b005b61030c600480360381019061030791906122f1565b61092e565b60405161031991906121e6565b60405180910390f35b61033c6004803603810190610337919061233e565b610994565b60405161034991906121e6565b60405180910390f35b61036c60048036038101906103679190612201565b6109c8565b6040516103799190612271565b60405180910390f35b61039c60048036038101906103979190612201565b6109ef565b005b6103b860048036038101906103b39190612391565b610a21565b6040516103c591906121e6565b60405180910390f35b6103d6610a55565b6040516103e3919061210e565b60405180910390f35b6103f4610a6d565b604051610401919061210e565b60405180910390f35b610412610a85565b60405161041f919061210e565b60405180910390f35b610442600480360381019061043d9190612391565b610a9d565b005b61044c610acf565b604051610459919061210e565b60405180910390f35b61046a610ae7565b604051610477919061210e565b60405180910390f35b610488610aff565b604051610495919061210e565b60405180910390f35b6104b860048036038101906104b39190612201565b610b17565b6040516104c59190612271565b60405180910390f35b6104e860048036038101906104e39190612414565b610b3e565b005b6104f2610b70565b6040516104ff9190612271565b60405180910390f35b610510610b94565b60405161051d9190612271565b60405180910390f35b61052e610bbc565b60405161053b919061210e565b60405180910390f35b61054c610bd4565b604051610559919061210e565b60405180910390f35b61056a610bec565b604051610577919061210e565b60405180910390f35b61059a60048036038101906105959190612414565b610c04565b005b6105a4610c36565b6040516105b19190612532565b60405180910390f35b6105d460048036038101906105cf9190612391565b610c45565b005b6105f060048036038101906105eb919061218b565b610c77565b6040516105fd91906121e6565b60405180910390f35b61060e610cab565b60405161061b919061210e565b60405180910390f35b61062c610cc3565b604051610639919061210e565b60405180910390f35b61064a610cdb565b6040516106579190612271565b60405180910390f35b610668610ce7565b6040516106759190612271565b60405180910390f35b61069860048036038101906106939190612554565b610d0b565b6040516106a59190612271565b60405180910390f35b6106b6610d3f565b6040516106c3919061210e565b60405180910390f35b6106d4610d57565b005b6106de610d59565b6040516106eb919061210e565b60405180910390f35b6106fc610d71565b60405161070991906121e6565b60405180910390f35b61072c60048036038101906107279190612391565b610da5565b604051610739919061210e565b60405180910390f35b61075c60048036038101906107579190612201565b610dd0565b60405161076a92919061262d565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156107af576107ae61265d565b5b6040519080825280602002602001820160405280156107dd5781602001602082028036833780820191505090505b50905060005b7f000000000000000000000000000000000000000000000000000000000000000081101561084057670de0b6b3a76400008282815181106108275761082661268c565b5b60200260200101818152505080806001019150506107e3565b5090565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b838390508110156109885761096d8484838181106109535761095261268c565b5b90506020020160208101906109689190612201565b611548565b61097b57600091505061098e565b8080600101915050610932565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006109d382611548565b6109de5760006109e8565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73a7241994267682de4de7ef62f52dc2c783d1784b81565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b736eed457c20603edae50c3a112caa1a9425321bd081565b6000610b2282611548565b610b2d576000610b37565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73281754ab58391a478b7aa4e7f39991cfb41118c481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610c406119a0565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b565b732f85824b2b38f179e451988670935d315b5b969281565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610daf6119a0565b8281518110610dc157610dc061268c565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e5b57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611543565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610ee257826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611543565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f6957826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611543565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fd357826040518060600160405280602281526020016126df6022913991509150611543565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361105a57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611543565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110c457826040518060600160405280602381526020016126bc6023913991509150611543565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361114b57826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611543565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111b557826040518060600160405280602781526020016127256027913991509150611543565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361123c57826040518060400160405280601981526020017f68747470733a2f2f756d622e686173686b65792e636c6f75640000000000000081525091509150611543565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112a657826040518060600160405280602481526020016127016024913991509150611543565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361132d57826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611543565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113b457826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611543565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361143b57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611543565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114a5578260405180606001604052806023815260200161274c6023913991509150611543565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152c57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611543565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806115d7575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061162157507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061166b575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116b557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116ff575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061174957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611793575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806117dd5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611827575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061187157507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806118bb5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611905575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061194f5750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611999575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156119de576119dd61265d565b5b604051908082528060200260200182016040528015611a0c5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611a3857611a3761268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611a9b57611a9a61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611afe57611afd61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611b6157611b6061268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac81600481518110611bc457611bc361268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a3881600581518110611c2757611c2661268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa471965311181600681518110611c8a57611c8961268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b81600781518110611ced57611cec61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff2714481600881518110611d5057611d4f61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600981518110611db357611db261268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600a81518110611e1657611e1561268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600b81518110611e7957611e7861268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600c81518110611edc57611edb61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081600d81518110611f3f57611f3e61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81600e81518110611fa257611fa161268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6120228161200f565b82525050565b60006120348383612019565b60208301905092915050565b6000602082019050919050565b600061205882611fe3565b6120628185611fee565b935061206d83611fff565b8060005b8381101561209e5781516120858882612028565b975061209083612040565b925050600181019050612071565b5085935050505092915050565b600060208201905081810360008301526120c5818461204d565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006120f8826120cd565b9050919050565b612108816120ed565b82525050565b600060208201905061212360008301846120ff565b92915050565b600080fd5b600080fd5b61213c816120ed565b811461214757600080fd5b50565b60008135905061215981612133565b92915050565b6121688161200f565b811461217357600080fd5b50565b6000813590506121858161215f565b92915050565b600080604083850312156121a2576121a1612129565b5b60006121b08582860161214a565b92505060206121c185828601612176565b9150509250929050565b60008115159050919050565b6121e0816121cb565b82525050565b60006020820190506121fb60008301846121d7565b92915050565b60006020828403121561221757612216612129565b5b60006122258482850161214a565b91505092915050565b6000819050919050565b6122418161222e565b82525050565b600060208201905061225c6000830184612238565b92915050565b61226b8161200f565b82525050565b60006020820190506122866000830184612262565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126122b1576122b061228c565b5b8235905067ffffffffffffffff8111156122ce576122cd612291565b5b6020830191508360208202830111156122ea576122e9612296565b5b9250929050565b6000806020838503121561230857612307612129565b5b600083013567ffffffffffffffff8111156123265761232561212e565b5b6123328582860161229b565b92509250509250929050565b60008060006060848603121561235757612356612129565b5b60006123658682870161214a565b93505060206123768682870161214a565b925050604061238786828701612176565b9150509250925092565b6000602082840312156123a7576123a6612129565b5b60006123b584828501612176565b91505092915050565b60008083601f8401126123d4576123d361228c565b5b8235905067ffffffffffffffff8111156123f1576123f0612291565b5b60208301915083600182028301111561240d5761240c612296565b5b9250929050565b60008060006040848603121561242d5761242c612129565b5b600061243b8682870161214a565b935050602084013567ffffffffffffffff81111561245c5761245b61212e565b5b612468868287016123be565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6124a9816120ed565b82525050565b60006124bb83836124a0565b60208301905092915050565b6000602082019050919050565b60006124df82612474565b6124e9818561247f565b93506124f483612490565b8060005b8381101561252557815161250c88826124af565b9750612517836124c7565b9250506001810190506124f8565b5085935050505092915050565b6000602082019050818103600083015261254c81846124d4565b905092915050565b6000806040838503121561256b5761256a612129565b5b60006125798582860161214a565b925050602061258a8582860161214a565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156125ce5780820151818401526020810190506125b3565b838111156125dd576000848401525b50505050565b6000601f19601f8301169050919050565b60006125ff82612594565b612609818561259f565b93506126198185602086016125b0565b612622816125e3565b840191505092915050565b600060408201905061264260008301856120ff565b818103602083015261265481846125f4565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6da2646970667358221220b875faa4ff94a6ed380db1c82cfc4fcfdce28d00988b3f85c113e0332affbaa264736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101ed5760003560e01c8062113e08146101f2578063015f7ed61461021057806303a1e2241461022e578063095ea7b31461024c5780630db18e371461027c57806317d7de7c146102ac57806318160ddd146102ca5780631aa3a008146102e85780631d4f9ce0146102f257806323b872dd1461032257806327e235e31461035257806329092d0e146103825780632e1a7d4d1461039e578063398b056e146103ce578063411ff497146103ec57806345f9f8251461040a57806352b41e351461042857806354755335146104445780635dc4bfd31461046257806369dc7ae41461048057806370a082311461049e578063838e7c3a146104ce578063902d55a5146104ea5780639031d9131461050857806390ff7e2e14610526578063989b6996146105445780639f0e948414610562578063a15ab08d14610580578063a39fac121461059c578063a694fc3a146105ba578063a9059cbb146105d6578063b2119eac14610606578063b49b084214610624578063c2ee3a0814610642578063db73177714610660578063dd62ed3e1461067e578063e2dc7a1a146106ae578063e79a198f146106cc578063e985e008146106d6578063e9fad8ee146106f4578063edf26d9b14610712578063fa52c7d814610742575b600080fd5b6101fa610773565b60405161020791906120ab565b60405180910390f35b610218610844565b604051610225919061210e565b60405180910390f35b61023661085c565b604051610243919061210e565b60405180910390f35b6102666004803603810190610261919061218b565b610874565b60405161027391906121e6565b60405180910390f35b61029660048036038101906102919190612201565b6108a8565b6040516102a391906121e6565b60405180910390f35b6102b46108dc565b6040516102c19190612247565b60405180910390f35b6102d2610904565b6040516102df9190612271565b60405180910390f35b6102f061092c565b005b61030c600480360381019061030791906122f1565b61092e565b60405161031991906121e6565b60405180910390f35b61033c6004803603810190610337919061233e565b610994565b60405161034991906121e6565b60405180910390f35b61036c60048036038101906103679190612201565b6109c8565b6040516103799190612271565b60405180910390f35b61039c60048036038101906103979190612201565b6109ef565b005b6103b860048036038101906103b39190612391565b610a21565b6040516103c591906121e6565b60405180910390f35b6103d6610a55565b6040516103e3919061210e565b60405180910390f35b6103f4610a6d565b604051610401919061210e565b60405180910390f35b610412610a85565b60405161041f919061210e565b60405180910390f35b610442600480360381019061043d9190612391565b610a9d565b005b61044c610acf565b604051610459919061210e565b60405180910390f35b61046a610ae7565b604051610477919061210e565b60405180910390f35b610488610aff565b604051610495919061210e565b60405180910390f35b6104b860048036038101906104b39190612201565b610b17565b6040516104c59190612271565b60405180910390f35b6104e860048036038101906104e39190612414565b610b3e565b005b6104f2610b70565b6040516104ff9190612271565b60405180910390f35b610510610b94565b60405161051d9190612271565b60405180910390f35b61052e610bbc565b60405161053b919061210e565b60405180910390f35b61054c610bd4565b604051610559919061210e565b60405180910390f35b61056a610bec565b604051610577919061210e565b60405180910390f35b61059a60048036038101906105959190612414565b610c04565b005b6105a4610c36565b6040516105b19190612532565b60405180910390f35b6105d460048036038101906105cf9190612391565b610c45565b005b6105f060048036038101906105eb919061218b565b610c77565b6040516105fd91906121e6565b60405180910390f35b61060e610cab565b60405161061b919061210e565b60405180910390f35b61062c610cc3565b604051610639919061210e565b60405180910390f35b61064a610cdb565b6040516106579190612271565b60405180910390f35b610668610ce7565b6040516106759190612271565b60405180910390f35b61069860048036038101906106939190612554565b610d0b565b6040516106a59190612271565b60405180910390f35b6106b6610d3f565b6040516106c3919061210e565b60405180910390f35b6106d4610d57565b005b6106de610d59565b6040516106eb919061210e565b60405180910390f35b6106fc610d71565b60405161070991906121e6565b60405180910390f35b61072c60048036038101906107279190612391565b610da5565b604051610739919061210e565b60405180910390f35b61075c60048036038101906107579190612201565b610dd0565b60405161076a92919061262d565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156107af576107ae61265d565b5b6040519080825280602002602001820160405280156107dd5781602001602082028036833780820191505090505b50905060005b7f000000000000000000000000000000000000000000000000000000000000000081101561084057670de0b6b3a76400008282815181106108275761082661268c565b5b60200260200101818152505080806001019150506107e3565b5090565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b838390508110156109885761096d8484838181106109535761095261268c565b5b90506020020160208101906109689190612201565b611548565b61097b57600091505061098e565b8080600101915050610932565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006109d382611548565b6109de5760006109e8565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73a7241994267682de4de7ef62f52dc2c783d1784b81565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b736eed457c20603edae50c3a112caa1a9425321bd081565b6000610b2282611548565b610b2d576000610b37565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73281754ab58391a478b7aa4e7f39991cfb41118c481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610c406119a0565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b565b732f85824b2b38f179e451988670935d315b5b969281565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610daf6119a0565b8281518110610dc157610dc061268c565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e5b57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611543565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610ee257826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611543565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f6957826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611543565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fd357826040518060600160405280602281526020016126df6022913991509150611543565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361105a57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611543565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110c457826040518060600160405280602381526020016126bc6023913991509150611543565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361114b57826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611543565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111b557826040518060600160405280602781526020016127256027913991509150611543565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361123c57826040518060400160405280601981526020017f68747470733a2f2f756d622e686173686b65792e636c6f75640000000000000081525091509150611543565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112a657826040518060600160405280602481526020016127016024913991509150611543565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361132d57826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611543565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113b457826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611543565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361143b57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611543565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114a5578260405180606001604052806023815260200161274c6023913991509150611543565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152c57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611543565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806115d7575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061162157507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061166b575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116b557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116ff575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061174957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611793575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806117dd5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611827575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061187157507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806118bb5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611905575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061194f5750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611999575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156119de576119dd61265d565b5b604051908082528060200260200182016040528015611a0c5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611a3857611a3761268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611a9b57611a9a61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611afe57611afd61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611b6157611b6061268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac81600481518110611bc457611bc361268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a3881600581518110611c2757611c2661268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa471965311181600681518110611c8a57611c8961268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b81600781518110611ced57611cec61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff2714481600881518110611d5057611d4f61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600981518110611db357611db261268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600a81518110611e1657611e1561268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600b81518110611e7957611e7861268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600c81518110611edc57611edb61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081600d81518110611f3f57611f3e61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81600e81518110611fa257611fa161268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6120228161200f565b82525050565b60006120348383612019565b60208301905092915050565b6000602082019050919050565b600061205882611fe3565b6120628185611fee565b935061206d83611fff565b8060005b8381101561209e5781516120858882612028565b975061209083612040565b925050600181019050612071565b5085935050505092915050565b600060208201905081810360008301526120c5818461204d565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006120f8826120cd565b9050919050565b612108816120ed565b82525050565b600060208201905061212360008301846120ff565b92915050565b600080fd5b600080fd5b61213c816120ed565b811461214757600080fd5b50565b60008135905061215981612133565b92915050565b6121688161200f565b811461217357600080fd5b50565b6000813590506121858161215f565b92915050565b600080604083850312156121a2576121a1612129565b5b60006121b08582860161214a565b92505060206121c185828601612176565b9150509250929050565b60008115159050919050565b6121e0816121cb565b82525050565b60006020820190506121fb60008301846121d7565b92915050565b60006020828403121561221757612216612129565b5b60006122258482850161214a565b91505092915050565b6000819050919050565b6122418161222e565b82525050565b600060208201905061225c6000830184612238565b92915050565b61226b8161200f565b82525050565b60006020820190506122866000830184612262565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126122b1576122b061228c565b5b8235905067ffffffffffffffff8111156122ce576122cd612291565b5b6020830191508360208202830111156122ea576122e9612296565b5b9250929050565b6000806020838503121561230857612307612129565b5b600083013567ffffffffffffffff8111156123265761232561212e565b5b6123328582860161229b565b92509250509250929050565b60008060006060848603121561235757612356612129565b5b60006123658682870161214a565b93505060206123768682870161214a565b925050604061238786828701612176565b9150509250925092565b6000602082840312156123a7576123a6612129565b5b60006123b584828501612176565b91505092915050565b60008083601f8401126123d4576123d361228c565b5b8235905067ffffffffffffffff8111156123f1576123f0612291565b5b60208301915083600182028301111561240d5761240c612296565b5b9250929050565b60008060006040848603121561242d5761242c612129565b5b600061243b8682870161214a565b935050602084013567ffffffffffffffff81111561245c5761245b61212e565b5b612468868287016123be565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6124a9816120ed565b82525050565b60006124bb83836124a0565b60208301905092915050565b6000602082019050919050565b60006124df82612474565b6124e9818561247f565b93506124f483612490565b8060005b8381101561252557815161250c88826124af565b9750612517836124c7565b9250506001810190506124f8565b5085935050505092915050565b6000602082019050818103600083015261254c81846124d4565b905092915050565b6000806040838503121561256b5761256a612129565b5b60006125798582860161214a565b925050602061258a8582860161214a565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156125ce5780820151818401526020810190506125b3565b838111156125dd576000848401525b50505050565b6000601f19601f8301169050919050565b60006125ff82612594565b612609818561259f565b93506126198185602086016125b0565b612622816125e3565b840191505092915050565b600060408201905061264260008301856120ff565b818103602083015261265481846125f4565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6da2646970667358221220b875faa4ff94a6ed380db1c82cfc4fcfdce28d00988b3f85c113e0332affbaa264736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/arbitrum_production/UmbrellaFeeds.json b/deployments/arbitrum_production/UmbrellaFeeds.json index c1a84cff..7e6402aa 100644 --- a/deployments/arbitrum_production/UmbrellaFeeds.json +++ b/deployments/arbitrum_production/UmbrellaFeeds.json @@ -1,5 +1,5 @@ { - "address": "0xa90068CDC31812d075E4Eb5b88b3ED8137EE4A9F", + "address": "0x648F235ec0C24fe170BD0822d2FEf442880A25EE", "abi": [ { "inputs": [ @@ -662,19 +662,19 @@ "type": "function" } ], - "transactionHash": "0x4f3d064b1ca7934a6a364e529b606058a2e9182d61343a7089460d439408a449", + "transactionHash": "0x5be7acbd0a3f50d90a61b23c846b287f6424b5c485e84815c950ee0843e97190", "receipt": { "to": null, "from": "0xA6e4fFa19B213AbeA258ae72e8e1a209B9E543e7", - "contractAddress": "0xa90068CDC31812d075E4Eb5b88b3ED8137EE4A9F", - "transactionIndex": 6, - "gasUsed": "18585933", + "contractAddress": "0x648F235ec0C24fe170BD0822d2FEf442880A25EE", + "transactionIndex": 5, + "gasUsed": "4984859", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xae0d9301891c211c45294d2b9c2f2c6ed22734cf6f66c4a03d45e155e9f8abe1", - "transactionHash": "0x4f3d064b1ca7934a6a364e529b606058a2e9182d61343a7089460d439408a449", + "blockHash": "0xf68da021b8b6d0450c2f3596844f6abcce8af200a04490604c907062e82d0d09", + "transactionHash": "0x5be7acbd0a3f50d90a61b23c846b287f6424b5c485e84815c950ee0843e97190", "logs": [], - "blockNumber": 147998709, - "cumulativeGasUsed": "21874665", + "blockNumber": 269196287, + "cumulativeGasUsed": "5681770", "status": 1, "byzantium": true }, @@ -684,7 +684,7 @@ 8 ], "numDeployments": 1, - "solcInputHash": "4db3e1d3dd51dbe508dc0a6a04352df6", + "solcInputHash": "dc68422c0ad35a4fe46d461b096b9383", "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"_contractRegistry\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"_requiredSignatures\",\"type\":\"uint16\"},{\"internalType\":\"uint8\",\"name\":\"_decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ArraysDataDoNotMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractInUse\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractNotInitialised\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ECDSAInvalidSignatureS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ECDSAInvalidSignatureV\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FeedNotExist\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRequiredSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotEnoughSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OldData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfOrder\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DECIMALS\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DEPLOYED_AT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ETH_PREFIX\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NAME\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REGISTRY\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REQUIRED_SIGNATURES\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"STAKING_BANK\",\"outputs\":[{\"internalType\":\"contract IStakingBankStatic\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"destroy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_keys\",\"type\":\"bytes32[]\"}],\"name\":\"getManyPriceData\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData[]\",\"name\":\"data\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_keys\",\"type\":\"bytes32[]\"}],\"name\":\"getManyPriceDataRaw\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData[]\",\"name\":\"data\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getPrice\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getPriceData\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData\",\"name\":\"data\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"getPriceDataByName\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData\",\"name\":\"data\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getPriceTimestamp\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getPriceTimestampHeartbeat\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_priceKeys\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData[]\",\"name\":\"_priceDatas\",\"type\":\"tuple[]\"}],\"name\":\"hashData\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"prices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData\",\"name\":\"data\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_hash\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"_v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"_r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_s\",\"type\":\"bytes32\"}],\"name\":\"recoverSigner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_priceKeys\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData[]\",\"name\":\"_priceDatas\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"struct IUmbrellaFeeds.Signature[]\",\"name\":\"_signatures\",\"type\":\"tuple[]\"}],\"name\":\"update\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_hash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"struct IUmbrellaFeeds.Signature[]\",\"name\":\"_signatures\",\"type\":\"tuple[]\"}],\"name\":\"verifySignatures\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Main contract for all on-chain data. Check `UmbrellaFeedsReader` to see how to integrate.\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_contractRegistry\":\"Registry address\",\"_decimals\":\"decimals for prices stored in this contract\",\"_requiredSignatures\":\"number of required signatures for accepting consensus submission\"}},\"destroy(string)\":{\"details\":\"destroys old contract there is sanity check that prevents abuse of destroy method\",\"params\":{\"_name\":\"string feed key to verify, that contract was initialised\"}},\"getManyPriceData(bytes32[])\":{\"details\":\"it will return array of price datas for provided `_keys` In case ony of feed does not exist, fallback call will be executed for that feed.\",\"params\":{\"_keys\":\"array of feed keys\"},\"returns\":{\"data\":\"PriceData array\"}},\"getManyPriceDataRaw(bytes32[])\":{\"details\":\"same as getManyPriceData() but does not revert on empty data.\"},\"getName()\":{\"details\":\"to follow Registrable interface\"},\"getPrice(bytes32)\":{\"params\":{\"_key\":\"hash of feed name\"},\"returns\":{\"price\":\"price\"}},\"getPriceData(bytes32)\":{\"details\":\"this is main endpoint for reading feeds. In case timestamp is empty (that means there is no data), contract will revert. If you do not need whole data from `PriceData` struct, you can save some gas by using other view methods that returns just what you need.\",\"params\":{\"_key\":\"hash of feed name\"},\"returns\":{\"data\":\"full PriceData struct\"}},\"getPriceDataByName(string)\":{\"details\":\"This method should be used only for Layer2 as it is more gas consuming than others views.\",\"params\":{\"_name\":\"string feed name\"},\"returns\":{\"data\":\"PriceData\"}},\"getPriceTimestamp(bytes32)\":{\"params\":{\"_key\":\"hash of feed name\"},\"returns\":{\"price\":\"price\",\"timestamp\":\"timestamp\"}},\"getPriceTimestampHeartbeat(bytes32)\":{\"params\":{\"_key\":\"hash of feed name\"},\"returns\":{\"heartbeat\":\"heartbeat\",\"price\":\"price\",\"timestamp\":\"timestamp\"}},\"hashData(bytes32[],(uint8,uint24,uint32,uint128)[])\":{\"details\":\"helper method for QA purposes\",\"returns\":{\"_0\":\"hash of data that are signed by validators (keys and priced data)\"}},\"prices(bytes32)\":{\"params\":{\"_key\":\"hash of feed name\"},\"returns\":{\"data\":\"full PriceData struct\"}},\"recoverSigner(bytes32,uint8,bytes32,bytes32)\":{\"params\":{\"_hash\":\"hashed of data\",\"_r\":\"part of signature\",\"_s\":\"part of signature\",\"_v\":\"part of signature\"},\"returns\":{\"_0\":\"signer address\"}},\"update(bytes32[],(uint8,uint24,uint32,uint128)[],(uint8,bytes32,bytes32)[])\":{\"details\":\"method for submitting consensus data\",\"params\":{\"_priceDatas\":\"PriceData signed by validators\",\"_priceKeys\":\"array of keys for `_priceDatas`\",\"_signatures\":\"validators signatures\"}},\"verifySignatures(bytes32,(uint8,bytes32,bytes32)[])\":{\"params\":{\"_hash\":\"hash of signed data\",\"_signatures\":\"array of validators signatures\"}}},\"stateVariables\":{\"DECIMALS\":{\"details\":\"decimals for prices stored in this contract\"},\"DEPLOYED_AT\":{\"details\":\"deployment time, used for protect for unintentional destroy\"},\"REGISTRY\":{\"details\":\"Registry contract where list of all addresses is stored. Fallback feature uses this registry to resolve newest `UmbrellaFeeds` address\"},\"REQUIRED_SIGNATURES\":{\"details\":\"minimal number of signatures required for accepting price submission (PoA)\"},\"STAKING_BANK\":{\"details\":\"StakingBank contract where list of validators is stored\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getManyPriceData(bytes32[])\":{\"notice\":\"If data for any key not exists, function will revert. Use `getManyPriceDataRaw` method if you don't want revert.\"},\"getManyPriceDataRaw(bytes32[])\":{\"notice\":\"This method does no revert if some data does not exists. Check `data.timestamp` to see if price exist, if it is 0, then it does not exist.\"},\"getPrice(bytes32)\":{\"notice\":\"method will revert if data for `_key` not exists.\"},\"getPriceData(bytes32)\":{\"notice\":\"method will revert if data for `_key` not exists.\"},\"getPriceDataByName(string)\":{\"notice\":\"It does not revert on empty data.\"},\"getPriceTimestamp(bytes32)\":{\"notice\":\"method will revert if data for `_key` not exists.\"},\"getPriceTimestampHeartbeat(bytes32)\":{\"notice\":\"method will revert if data for `_key` not exists.\"},\"prices(bytes32)\":{\"notice\":\"reader for mapping\"}},\"notice\":\"This contract can be destroyed and replaced with new one (with new address). For best gas efficiency you should pick one of two ways of integration: 1. make `UmbrellaFeeds` immutable and use fallback in case of selfdestruct. After new deployment, it is recommended to update address to avoid fallback and reduce gas cost to minimum. In long run this is most efficient solution, better than any proxy. 2. always check newest `UmbrellaFeeds` via `Regostry` and fallback will not be needed.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/onChainFeeds/UmbrellaFeeds.sol\":\"UmbrellaFeeds\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":0},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/interfaces/IRegistry.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\n\\ninterface IRegistry {\\n event LogRegistered(address indexed destination, bytes32 name);\\n\\n /// @dev imports new contract addresses and override old addresses, if they exist under provided name\\n /// This method can be used for contracts that for some reason do not have `getName` method\\n /// @param _names array of contract names that we want to register\\n /// @param _destinations array of contract addresses\\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external;\\n\\n /// @dev imports new contracts and override old addresses, if they exist.\\n /// Names of contracts are fetched directly from each contract by calling `getName`\\n /// @param _destinations array of contract addresses\\n function importContracts(address[] calldata _destinations) external;\\n\\n /// @dev this method ensure, that old and new contract is aware of it state in registry\\n /// Note: BSC registry does not have this method. This method was introduced in later stage.\\n /// @param _newContract address of contract that will replace old one\\n function atomicUpdate(address _newContract) external;\\n\\n /// @dev similar to `getAddress` but throws when contract name not exists\\n /// @param name contract name\\n /// @return contract address registered under provided name or throws, if does not exists\\n function requireAndGetAddress(bytes32 name) external view returns (address);\\n\\n /// @param name contract name in a form of bytes32\\n /// @return contract address registered under provided name\\n function getAddress(bytes32 name) external view returns (address);\\n\\n /// @param _name contract name\\n /// @return contract address assigned to the name or address(0) if not exists\\n function getAddressByString(string memory _name) external view returns (address);\\n\\n /// @dev helper method that converts string to bytes32,\\n /// you can use to to generate contract name\\n function stringToBytes32(string memory _string) external pure returns (bytes32 result);\\n}\\n\",\"keccak256\":\"0xa0099ecf4182138fda7a0733407784461410c245de67c1e7ba7cd7c9595e054f\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBank.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IStakingBank is IERC20 {\\n /// @param id address of validator wallet\\n /// @param location URL of the validator API\\n struct Validator {\\n address id;\\n string location;\\n }\\n\\n event LogValidatorRegistered(address indexed id);\\n event LogValidatorUpdated(address indexed id);\\n event LogValidatorRemoved(address indexed id);\\n event LogMinAmountForStake(uint256 minAmountForStake);\\n\\n /// @dev setter for `minAmountForStake`\\n function setMinAmountForStake(uint256 _minAmountForStake) external;\\n\\n /// @dev allows to stake `token` by validators\\n /// Validator needs to approve StakingBank beforehand\\n /// @param _value amount of tokens to stake\\n function stake(uint256 _value) external;\\n\\n /// @dev notification about approval from `_from` address on UMB token\\n /// Staking bank will stake max approved amount from `_from` address\\n /// @param _from address which approved token spend for IStakingBank\\n function receiveApproval(address _from) external returns (bool success);\\n\\n /// @dev withdraws stake tokens\\n /// it throws, when balance will be less than required minimum for stake\\n /// to withdraw all use `exit`\\n function withdraw(uint256 _value) external returns (bool success);\\n\\n /// @dev unstake and withdraw all tokens\\n function exit() external returns (bool success);\\n\\n /// @dev creates (register) new validator\\n /// @param _id validator address\\n /// @param _location location URL of the validator API\\n function create(address _id, string calldata _location) external;\\n\\n /// @dev removes validator\\n /// @param _id validator wallet\\n function remove(address _id) external;\\n\\n /// @dev updates validator location\\n /// @param _id validator wallet\\n /// @param _location new validator URL\\n function update(address _id, string calldata _location) external;\\n\\n /// @return total number of registered validators (with and without balance)\\n function getNumberOfValidators() external view returns (uint256);\\n\\n /// @dev gets validator address for provided index\\n /// @param _ix index in array of list of all validators wallets\\n function addresses(uint256 _ix) external view returns (address);\\n\\n /// @param _id address of validator\\n /// @return id address of validator\\n /// @return location URL of validator\\n function validators(address _id) external view returns (address id, string memory location);\\n}\\n\",\"keccak256\":\"0x2c518aeab8b0b3a364fafaec559d3ff0dc6a119f8d203fa31ef7ad667ca0f7b9\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBankStatic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./IStakingBank.sol\\\";\\n\\n\\ninterface IStakingBankStatic is IStakingBank {\\n /// @param _validators array of validators addresses to verify\\n /// @return TRUE when all validators are valid, FALSE otherwise\\n function verifyValidators(address[] calldata _validators) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xb7829f090205357ae8c7b86490504897060650c149309362b95eacbeef88d8ba\",\"license\":\"MIT\"},\"contracts/interfaces/IUmbrellaFeeds.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IUmbrellaFeeds {\\n struct PriceData {\\n /// @dev this is placeholder, that can be used for some additional data\\n /// atm of creating this smart contract, it is only used as marker for removed data (when == type(uint8).max)\\n uint8 data;\\n /// @dev heartbeat: how often price data will be refreshed in case price stay flat\\n uint24 heartbeat;\\n /// @dev timestamp: price time, at this time validators run consensus\\n uint32 timestamp;\\n /// @dev price\\n uint128 price;\\n }\\n\\n struct Signature {\\n uint8 v;\\n bytes32 r;\\n bytes32 s;\\n }\\n\\n /// @dev method for submitting consensus data\\n /// @param _priceKeys array of keys for `_priceDatas`\\n /// @param _priceDatas PriceData signed by validators\\n /// @param _signatures validators signatures\\n function update(\\n bytes32[] calldata _priceKeys,\\n PriceData[] calldata _priceDatas,\\n Signature[] calldata _signatures\\n ) external;\\n\\n /// @dev it will return array of price datas for provided `_keys`\\n /// In case ony of feed does not exist, fallback call will be executed for that feed.\\n /// @notice If data for any key not exists, function will revert. Use `getManyPriceDataRaw` method if you don't\\n /// want revert.\\n /// @param _keys array of feed keys\\n /// @return data PriceData array\\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data);\\n\\n /// @dev same as getManyPriceData() but does not revert on empty data.\\n /// @notice This method does no revert if some data does not exists.\\n /// Check `data.timestamp` to see if price exist, if it is 0, then it does not exist.\\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data);\\n\\n /// @dev this is main endpoint for reading feeds.\\n /// In case timestamp is empty (that means there is no data), contract will revert.\\n /// If you do not need whole data from `PriceData` struct, you can save some gas by using other view methods that\\n /// returns just what you need.\\n /// @notice method will revert if data for `_key` not exists.\\n /// @param _key hash of feed name\\n /// @return data full PriceData struct\\n function getPriceData(bytes32 _key) external view returns (PriceData memory data);\\n\\n /// @notice reader for mapping\\n /// @param _key hash of feed name\\n /// @return data full PriceData struct\\n function prices(bytes32 _key) external view returns (PriceData memory data);\\n\\n /// @notice method will revert if data for `_key` not exists.\\n /// @param _key hash of feed name\\n /// @return price\\n function getPrice(bytes32 _key) external view returns (uint128 price);\\n\\n /// @notice method will revert if data for `_key` not exists.\\n /// @param _key hash of feed name\\n /// @return price\\n /// @return timestamp\\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp);\\n\\n /// @notice method will revert if data for `_key` not exists.\\n /// @param _key hash of feed name\\n /// @return price\\n /// @return timestamp\\n /// @return heartbeat\\n function getPriceTimestampHeartbeat(bytes32 _key)\\n external\\n view\\n returns (uint128 price, uint32 timestamp, uint24 heartbeat);\\n\\n /// @dev This method should be used only for Layer2 as it is more gas consuming than others views.\\n /// @notice It does not revert on empty data.\\n /// @param _name string feed name\\n /// @return data PriceData\\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data);\\n\\n /// @dev decimals for prices stored in this contract\\n function DECIMALS() external view returns (uint8); // solhint-disable-line func-name-mixedcase\\n}\\n\",\"keccak256\":\"0x3b89742a9ab465f00aa9cf8635a5dfdc02d7ecf9bad8f564bee7c15d8aea46cb\",\"license\":\"MIT\"},\"contracts/onChainFeeds/UmbrellaFeeds.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"../interfaces/IUmbrellaFeeds.sol\\\";\\nimport \\\"../interfaces/IRegistry.sol\\\";\\nimport \\\"../interfaces/IStakingBankStatic.sol\\\";\\n\\n/// @dev Main contract for all on-chain data.\\n/// Check `UmbrellaFeedsReader` to see how to integrate.\\n///\\n/// @notice This contract can be destroyed and replaced with new one (with new address).\\n/// For best gas efficiency you should pick one of two ways of integration:\\n/// 1. make `UmbrellaFeeds` immutable and use fallback in case of selfdestruct. After new deployment, it is recommended\\n/// to update address to avoid fallback and reduce gas cost to minimum. In long run this is most efficient solution,\\n/// better than any proxy.\\n/// 2. always check newest `UmbrellaFeeds` via `Regostry` and fallback will not be needed.\\ncontract UmbrellaFeeds is IUmbrellaFeeds {\\n bytes constant public ETH_PREFIX = \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\";\\n string constant public NAME = \\\"UmbrellaFeeds\\\";\\n\\n /// @dev deployment time, used for protect for unintentional destroy\\n uint256 public immutable DEPLOYED_AT; // solhint-disable-line var-name-mixedcase\\n\\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\\n /// resolve newest `UmbrellaFeeds` address\\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\\n\\n /// @dev StakingBank contract where list of validators is stored\\n IStakingBankStatic public immutable STAKING_BANK; // solhint-disable-line var-name-mixedcase\\n\\n /// @dev minimal number of signatures required for accepting price submission (PoA)\\n uint16 public immutable REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\\n\\n /// @dev decimals for prices stored in this contract\\n uint8 public immutable DECIMALS; // solhint-disable-line var-name-mixedcase\\n\\n /// @notice map of all prices stored in this contract, key for map is hash of feed name\\n /// eg for \\\"ETH-USD\\\" feed, key will be hash(\\\"ETH-USD\\\")\\n mapping (bytes32 => PriceData) private _prices;\\n\\n error ArraysDataDoNotMatch();\\n error FeedNotExist();\\n error NotEnoughSignatures();\\n error InvalidSigner();\\n error InvalidRequiredSignatures();\\n error SignaturesOutOfOrder();\\n error ECDSAInvalidSignatureS();\\n error ECDSAInvalidSignatureV();\\n error OldData();\\n error ContractInUse();\\n error ContractNotInitialised();\\n\\n /// @param _contractRegistry Registry address\\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\\n /// @param _decimals decimals for prices stored in this contract\\n constructor(\\n IRegistry _contractRegistry,\\n uint16 _requiredSignatures,\\n uint8 _decimals\\n ) {\\n if (_requiredSignatures == 0) revert InvalidRequiredSignatures();\\n\\n REGISTRY = _contractRegistry;\\n REQUIRED_SIGNATURES = _requiredSignatures;\\n STAKING_BANK = IStakingBankStatic(_contractRegistry.requireAndGetAddress(\\\"StakingBank\\\"));\\n DECIMALS = _decimals;\\n DEPLOYED_AT = block.timestamp;\\n }\\n\\n /// @dev destroys old contract\\n /// there is sanity check that prevents abuse of destroy method\\n /// @param _name string feed key to verify, that contract was initialised\\n function destroy(string calldata _name) external {\\n if (REGISTRY.getAddressByString(NAME) == address(this)) revert ContractInUse();\\n\\n if (_prices[keccak256(abi.encodePacked(_name))].timestamp == 0 && DEPLOYED_AT + 3 days > block.timestamp) {\\n revert ContractNotInitialised();\\n }\\n\\n selfdestruct(payable(msg.sender));\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function update(\\n bytes32[] calldata _priceKeys,\\n PriceData[] calldata _priceDatas,\\n Signature[] calldata _signatures\\n ) external {\\n if (_priceKeys.length != _priceDatas.length) revert ArraysDataDoNotMatch();\\n\\n bytes32 priceDataHash = keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\\n verifySignatures(priceDataHash, _signatures);\\n\\n uint256 i;\\n\\n while (i < _priceDatas.length) {\\n bytes32 priceKey = _priceKeys[i];\\n\\n // we do not allow for older prices\\n // at the same time it prevents from reusing signatures\\n if (_prices[priceKey].timestamp >= _priceDatas[i].timestamp) revert OldData();\\n\\n _prices[priceKey] = _priceDatas[i];\\n\\n // atm there is no need for events, so in order to save gas, we do not emit any\\n unchecked { i++; }\\n }\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\\n data = new PriceData[](_keys.length);\\n\\n for (uint256 i; i < _keys.length;) {\\n data[i] = _prices[_keys[i]];\\n if (data[i].timestamp == 0) revert FeedNotExist();\\n\\n unchecked { i++; }\\n }\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\\n data = new PriceData[](_keys.length);\\n\\n for (uint256 i; i < _keys.length;) {\\n data[i] = _prices[_keys[i]];\\n unchecked { i++; }\\n }\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function prices(bytes32 _key) external view returns (PriceData memory data) {\\n data = _prices[_key];\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getPriceData(bytes32 _key) external view returns (PriceData memory data) {\\n data = _prices[_key];\\n if (data.timestamp == 0) revert FeedNotExist();\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getPrice(bytes32 _key) external view returns (uint128 price) {\\n PriceData memory data = _prices[_key];\\n if (data.timestamp == 0) revert FeedNotExist();\\n\\n return data.price;\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp) {\\n PriceData memory data = _prices[_key];\\n if (data.timestamp == 0) revert FeedNotExist();\\n\\n return (data.price, data.timestamp);\\n }\\n\\n function getPriceTimestampHeartbeat(bytes32 _key)\\n external\\n view\\n returns (uint128 price, uint32 timestamp, uint24 heartbeat)\\n {\\n PriceData memory data = _prices[_key];\\n if (data.timestamp == 0) revert FeedNotExist();\\n\\n return (data.price, data.timestamp, data.heartbeat);\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data) {\\n bytes32 key = keccak256(abi.encodePacked(_name));\\n data = _prices[key];\\n }\\n\\n /// @dev helper method for QA purposes\\n /// @return hash of data that are signed by validators (keys and priced data)\\n function hashData(bytes32[] calldata _priceKeys, PriceData[] calldata _priceDatas)\\n external\\n view\\n returns (bytes32)\\n {\\n return keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\\n }\\n\\n /// @param _hash hash of signed data\\n /// @param _signatures array of validators signatures\\n function verifySignatures(bytes32 _hash, Signature[] calldata _signatures) public view {\\n address prevSigner = address(0x0);\\n\\n if (_signatures.length < REQUIRED_SIGNATURES) revert NotEnoughSignatures();\\n\\n address[] memory validators = new address[](REQUIRED_SIGNATURES);\\n\\n // to save gas we check only required number of signatures\\n // case, where you can have part of signatures invalid but still enough valid in total is not supported\\n for (uint256 i; i < REQUIRED_SIGNATURES;) {\\n (uint8 v, bytes32 r, bytes32 s) = (_signatures[i].v, _signatures[i].r, _signatures[i].s);\\n\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n revert ECDSAInvalidSignatureS();\\n }\\n\\n if (uint8(v) != 27 && uint8(v) != 28) revert ECDSAInvalidSignatureV();\\n\\n address signer = recoverSigner(_hash, v, r, s);\\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\\n\\n // because we check only required number of signatures, any invalid one will cause revert\\n prevSigner = signer;\\n validators[i] = signer;\\n\\n unchecked { i++; }\\n }\\n\\n // bulk verification can optimise gas when we have 5 or more validators\\n if (!STAKING_BANK.verifyValidators(validators)) revert InvalidSigner();\\n }\\n\\n function getChainId() public view returns (uint256 id) {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n id := chainid()\\n }\\n }\\n\\n /// @param _hash hashed of data\\n /// @param _v part of signature\\n /// @param _r part of signature\\n /// @param _s part of signature\\n /// @return signer address\\n function recoverSigner(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _hash));\\n return ecrecover(hash, _v, _r, _s);\\n }\\n\\n /// @dev to follow Registrable interface\\n function getName() public pure returns (bytes32) {\\n return \\\"UmbrellaFeeds\\\";\\n }\\n}\\n\",\"keccak256\":\"0xf5dcfbbdfe5a5ed6e7579246363b10cdc0aa30580fec74025e0704c2b042d369\",\"license\":\"MIT\"}},\"version\":1}", "bytecode": "0x6101206040523480156200001257600080fd5b50604051620030a4380380620030a4833981810160405281019062000038919062000286565b60008261ffff160362000077576040517f458bb42100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff16815250508161ffff1660e08161ffff16815250508273ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b8152600401620000f49062000308565b602060405180830381865afa15801562000112573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000138919062000354565b73ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff16815250508060ff166101008160ff1681525050426080818152505050505062000386565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620001bd8262000190565b9050919050565b6000620001d182620001b0565b9050919050565b620001e381620001c4565b8114620001ef57600080fd5b50565b6000815190506200020381620001d8565b92915050565b600061ffff82169050919050565b620002228162000209565b81146200022e57600080fd5b50565b600081519050620002428162000217565b92915050565b600060ff82169050919050565b620002608162000248565b81146200026c57600080fd5b50565b600081519050620002808162000255565b92915050565b600080600060608486031215620002a257620002a16200018b565b5b6000620002b286828701620001f2565b9350506020620002c58682870162000231565b9250506040620002d8868287016200026f565b9150509250925092565b7f5374616b696e6742616e6b000000000000000000000000000000000000000000815250565b60006020820190506200031e60008301620002e2565b919050565b6200032e81620001b0565b81146200033a57600080fd5b50565b6000815190506200034e8162000323565b92915050565b6000602082840312156200036d576200036c6200018b565b5b60006200037d848285016200033d565b91505092915050565b60805160a05160c05160e05161010051612caf620003f560003960006108b10152600081816104e501528181610548015281816105ba01526116980152600081816107da01526116f501526000818161045e015261107e0152600081816111fd015261127a0152612caf6000f3fe608060405234801561001057600080fd5b50600436106101125760003560e01c806306433b1b1461011757806317d7de7c1461013557806324c89a491461015357806326559877146101715780632e0f26251461018d5780632e550693146101ab57806331d98b3f146101db5780633408e4701461020b578063385e05da1461022957806343fa6211146102595780635b38adc71461028957806360846bc6146102b95780636b9c3c7c146102e95780636ebb8cd2146103055780638a1194d31461032357806395f1cf301461035457806396594f66146103705780639ac18b19146103a2578063a3f4df7e146103c0578063c65a53ad146103de578063ccc6fd69146103fc578063d45167d01461042c575b600080fd5b61011f61045c565b60405161012c91906118df565b60405180910390f35b61013d610480565b60405161014a9190611913565b60405180910390f35b61015b6104a8565b60405161016891906119c7565b60405180910390f35b61018b60048036038101906101869190611a84565b6104e1565b005b6101956108af565b6040516101a29190611b00565b60405180910390f35b6101c560048036038101906101c09190611b71565b6108d3565b6040516101d29190611d39565b60405180910390f35b6101f560048036038101906101f09190611d5b565b610a54565b6040516102029190611d97565b60405180910390f35b610213610b77565b6040516102209190611dcb565b60405180910390f35b610243600480360381019061023e9190611b71565b610b7f565b6040516102509190611d39565b60405180910390f35b610273600480360381019061026e9190611d5b565b610d5e565b6040516102809190611e3b565b60405180910390f35b6102a3600480360381019061029e9190611eac565b610e7e565b6040516102b09190611e3b565b60405180910390f35b6102d360048036038101906102ce9190611d5b565b610f89565b6040516102e09190611e3b565b60405180910390f35b61030360048036038101906102fe9190611eac565b611065565b005b61030d611278565b60405161031a9190611dcb565b60405180910390f35b61033d60048036038101906103389190611d5b565b61129c565b60405161034b929190611f08565b60405180910390f35b61036e60048036038101906103699190611f87565b6113c8565b005b61038a60048036038101906103859190611d5b565b611560565b6040516103999392919061204a565b60405180910390f35b6103aa611696565b6040516103b7919061209e565b60405180910390f35b6103c86116ba565b6040516103d5919061210e565b60405180910390f35b6103e66116f3565b6040516103f39190612151565b60405180910390f35b6104166004803603810190610411919061216c565b611717565b6040516104239190611913565b60405180910390f35b61044660048036038101906104419190612219565b61175b565b60405161045391906122a1565b60405180910390f35b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f556d6272656c6c61466565647300000000000000000000000000000000000000905090565b6040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525081565b60007f000000000000000000000000000000000000000000000000000000000000000061ffff16838390501015610544576040517fe246dc6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000061ffff1667ffffffffffffffff811115610584576105836122bc565b5b6040519080825280602002602001820160405280156105b25781602001602082028036833780820191505090505b50905060005b7f000000000000000000000000000000000000000000000000000000000000000061ffff168110156107d75760008060008787858181106105fc576105fb6122eb565b5b9050606002016000016020810190610614919061231a565b888886818110610627576106266122eb565b5b90506060020160200135898987818110610644576106436122eb565b5b905060600201604001359250925092507f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08160001c11156106b1576040517f454ffaa700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601b8360ff16141580156106c95750601c8360ff1614155b15610700576040517f1afa741400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061070e8a85858561175b565b90508073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1610610775576040517f9079f69b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8096508086868151811061078c5761078b6122eb565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508480600101955050505050506105b8565b507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16631d4f9ce0826040518263ffffffff1660e01b81526004016108319190612405565b602060405180830381865afa15801561084e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610872919061245f565b6108a8576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60608282905067ffffffffffffffff8111156108f2576108f16122bc565b5b60405190808252806020026020018201604052801561092b57816020015b610918611818565b8152602001906001900390816109105790505b50905060005b83839050811015610a4d57600080858584818110610952576109516122eb565b5b9050602002013581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681525050828281518110610a3557610a346122eb565b5b60200260200101819052508080600101915050610931565b5092915050565b6000806000808481526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603610b6a576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060600151915050919050565b600046905090565b60608282905067ffffffffffffffff811115610b9e57610b9d6122bc565b5b604051908082528060200260200182016040528015610bd757816020015b610bc4611818565b815260200190600190039081610bbc5790505b50905060005b83839050811015610d5757600080858584818110610bfe57610bfd6122eb565b5b9050602002013581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681525050828281518110610ce157610ce06122eb565b5b60200260200101819052506000828281518110610d0157610d006122eb565b5b60200260200101516040015163ffffffff1603610d4a576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8080600101915050610bdd565b5092915050565b610d66611818565b6000808381526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603610e79576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b610e86611818565b60008383604051602001610e9b9291906124cb565b6040516020818303038152906040528051906020012090506000808281526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505091505092915050565b610f91611818565b6000808381526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815250509050919050565b3073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663e8f98f886040518060400160405280600d81526020017f556d6272656c6c614665656473000000000000000000000000000000000000008152506040518263ffffffff1660e01b815260040161110a919061210e565b602060405180830381865afa158015611127573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114b9190612510565b73ffffffffffffffffffffffffffffffffffffffff1603611198576040517f8c3e700900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600084846040516020016111b09291906124cb565b60405160208183030381529060405280519060200120815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff161480156112285750426203f4807f0000000000000000000000000000000000000000000000000000000000000000611226919061256c565b115b1561125f576040517fcf51b43b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff16ff5b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060008060008581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff16036113b4576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806060015181604001519250925050915091565b838390508686905014611407576040517f0cf7902300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611411610b77565b308888888860405160200161142b96959493929190612820565b60405160208183030381529060405280519060200120905061144e8184846104e1565b60005b85859050811015611556576000888883818110611471576114706122eb565b5b90506020020135905086868381811061148d5761148c6122eb565b5b90506080020160400160208101906114a59190612877565b63ffffffff1660008083815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff161061150e576040517f1251b2f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b868683818110611521576115206122eb565b5b90506080020160008083815260200190815260200160002081816115459190612ba1565b905050818060010192505050611451565b5050505050505050565b6000806000806000808681526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603611679576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806060015181604001518260200151935093509350509193909250565b7f000000000000000000000000000000000000000000000000000000000000000081565b6040518060400160405280600d81526020017f556d6272656c6c6146656564730000000000000000000000000000000000000081525081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000611721610b77565b308686868660405160200161173b96959493929190612820565b604051602081830303815290604052805190602001209050949350505050565b6000806040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250866040516020016117a6929190612c0c565b604051602081830303815290604052805190602001209050600181868686604051600081526020016040526040516117e19493929190612c34565b6020604051602081039080840390855afa158015611803573d6000803e3d6000fd5b50505060206040510351915050949350505050565b6040518060800160405280600060ff168152602001600062ffffff168152602001600063ffffffff16815260200160006fffffffffffffffffffffffffffffffff1681525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006118a56118a061189b84611860565b611880565b611860565b9050919050565b60006118b78261188a565b9050919050565b60006118c9826118ac565b9050919050565b6118d9816118be565b82525050565b60006020820190506118f460008301846118d0565b92915050565b6000819050919050565b61190d816118fa565b82525050565b60006020820190506119286000830184611904565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561196857808201518184015260208101905061194d565b83811115611977576000848401525b50505050565b6000601f19601f8301169050919050565b60006119998261192e565b6119a38185611939565b93506119b381856020860161194a565b6119bc8161197d565b840191505092915050565b600060208201905081810360008301526119e1818461198e565b905092915050565b600080fd5b600080fd5b6119fc816118fa565b8114611a0757600080fd5b50565b600081359050611a19816119f3565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112611a4457611a43611a1f565b5b8235905067ffffffffffffffff811115611a6157611a60611a24565b5b602083019150836060820283011115611a7d57611a7c611a29565b5b9250929050565b600080600060408486031215611a9d57611a9c6119e9565b5b6000611aab86828701611a0a565b935050602084013567ffffffffffffffff811115611acc57611acb6119ee565b5b611ad886828701611a2e565b92509250509250925092565b600060ff82169050919050565b611afa81611ae4565b82525050565b6000602082019050611b156000830184611af1565b92915050565b60008083601f840112611b3157611b30611a1f565b5b8235905067ffffffffffffffff811115611b4e57611b4d611a24565b5b602083019150836020820283011115611b6a57611b69611a29565b5b9250929050565b60008060208385031215611b8857611b876119e9565b5b600083013567ffffffffffffffff811115611ba657611ba56119ee565b5b611bb285828601611b1b565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b611bf381611ae4565b82525050565b600062ffffff82169050919050565b611c1181611bf9565b82525050565b600063ffffffff82169050919050565b611c3081611c17565b82525050565b60006fffffffffffffffffffffffffffffffff82169050919050565b611c5b81611c36565b82525050565b608082016000820151611c776000850182611bea565b506020820151611c8a6020850182611c08565b506040820151611c9d6040850182611c27565b506060820151611cb06060850182611c52565b50505050565b6000611cc28383611c61565b60808301905092915050565b6000602082019050919050565b6000611ce682611bbe565b611cf08185611bc9565b9350611cfb83611bda565b8060005b83811015611d2c578151611d138882611cb6565b9750611d1e83611cce565b925050600181019050611cff565b5085935050505092915050565b60006020820190508181036000830152611d538184611cdb565b905092915050565b600060208284031215611d7157611d706119e9565b5b6000611d7f84828501611a0a565b91505092915050565b611d9181611c36565b82525050565b6000602082019050611dac6000830184611d88565b92915050565b6000819050919050565b611dc581611db2565b82525050565b6000602082019050611de06000830184611dbc565b92915050565b608082016000820151611dfc6000850182611bea565b506020820151611e0f6020850182611c08565b506040820151611e226040850182611c27565b506060820151611e356060850182611c52565b50505050565b6000608082019050611e506000830184611de6565b92915050565b60008083601f840112611e6c57611e6b611a1f565b5b8235905067ffffffffffffffff811115611e8957611e88611a24565b5b602083019150836001820283011115611ea557611ea4611a29565b5b9250929050565b60008060208385031215611ec357611ec26119e9565b5b600083013567ffffffffffffffff811115611ee157611ee06119ee565b5b611eed85828601611e56565b92509250509250929050565b611f0281611c17565b82525050565b6000604082019050611f1d6000830185611d88565b611f2a6020830184611ef9565b9392505050565b60008083601f840112611f4757611f46611a1f565b5b8235905067ffffffffffffffff811115611f6457611f63611a24565b5b602083019150836080820283011115611f8057611f7f611a29565b5b9250929050565b60008060008060008060608789031215611fa457611fa36119e9565b5b600087013567ffffffffffffffff811115611fc257611fc16119ee565b5b611fce89828a01611b1b565b9650965050602087013567ffffffffffffffff811115611ff157611ff06119ee565b5b611ffd89828a01611f31565b9450945050604087013567ffffffffffffffff8111156120205761201f6119ee565b5b61202c89828a01611a2e565b92509250509295509295509295565b61204481611bf9565b82525050565b600060608201905061205f6000830186611d88565b61206c6020830185611ef9565b612079604083018461203b565b949350505050565b600061ffff82169050919050565b61209881612081565b82525050565b60006020820190506120b3600083018461208f565b92915050565b600081519050919050565b600082825260208201905092915050565b60006120e0826120b9565b6120ea81856120c4565b93506120fa81856020860161194a565b6121038161197d565b840191505092915050565b6000602082019050818103600083015261212881846120d5565b905092915050565b600061213b826118ac565b9050919050565b61214b81612130565b82525050565b60006020820190506121666000830184612142565b92915050565b60008060008060408587031215612186576121856119e9565b5b600085013567ffffffffffffffff8111156121a4576121a36119ee565b5b6121b087828801611b1b565b9450945050602085013567ffffffffffffffff8111156121d3576121d26119ee565b5b6121df87828801611f31565b925092505092959194509250565b6121f681611ae4565b811461220157600080fd5b50565b600081359050612213816121ed565b92915050565b60008060008060808587031215612233576122326119e9565b5b600061224187828801611a0a565b945050602061225287828801612204565b935050604061226387828801611a0a565b925050606061227487828801611a0a565b91505092959194509250565b600061228b82611860565b9050919050565b61229b81612280565b82525050565b60006020820190506122b66000830184612292565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156123305761232f6119e9565b5b600061233e84828501612204565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61237c81612280565b82525050565b600061238e8383612373565b60208301905092915050565b6000602082019050919050565b60006123b282612347565b6123bc8185612352565b93506123c783612363565b8060005b838110156123f85781516123df8882612382565b97506123ea8361239a565b9250506001810190506123cb565b5085935050505092915050565b6000602082019050818103600083015261241f81846123a7565b905092915050565b60008115159050919050565b61243c81612427565b811461244757600080fd5b50565b60008151905061245981612433565b92915050565b600060208284031215612475576124746119e9565b5b60006124838482850161244a565b91505092915050565b600081905092915050565b82818337600083830152505050565b60006124b2838561248c565b93506124bf838584612497565b82840190509392505050565b60006124d88284866124a6565b91508190509392505050565b6124ed81612280565b81146124f857600080fd5b50565b60008151905061250a816124e4565b92915050565b600060208284031215612526576125256119e9565b5b6000612534848285016124fb565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061257782611db2565b915061258283611db2565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156125b7576125b661253d565b5b828201905092915050565b600082825260208201905092915050565b600080fd5b60006125e483856125c2565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115612617576126166125d3565b5b602083029250612628838584612497565b82840190509392505050565b6000819050919050565b600061264d6020840184612204565b905092915050565b61265e81611bf9565b811461266957600080fd5b50565b60008135905061267b81612655565b92915050565b6000612690602084018461266c565b905092915050565b6126a181611c17565b81146126ac57600080fd5b50565b6000813590506126be81612698565b92915050565b60006126d360208401846126af565b905092915050565b6126e481611c36565b81146126ef57600080fd5b50565b600081359050612701816126db565b92915050565b600061271660208401846126f2565b905092915050565b6080820161272f600083018361263e565b61273c6000850182611bea565b5061274a6020830183612681565b6127576020850182611c08565b5061276560408301836126c4565b6127726040850182611c27565b506127806060830183612707565b61278d6060850182611c52565b50505050565b600061279f838361271e565b60808301905092915050565b600082905092915050565b6000608082019050919050565b60006127cf8385611bc9565b93506127da82612634565b8060005b85811015612813576127f082846127ab565b6127fa8882612793565b9750612805836127b6565b9250506001810190506127de565b5085925050509392505050565b60006080820190506128356000830189611dbc565b6128426020830188612292565b81810360408301526128558186886125d8565b9050818103606083015261286a8184866127c3565b9050979650505050505050565b60006020828403121561288d5761288c6119e9565b5b600061289b848285016126af565b91505092915050565b600081356128b1816121ed565b80915050919050565b60008160001b9050919050565b600060ff6128d4846128ba565b9350801983169250808416831791505092915050565b60006129056129006128fb84611ae4565b611880565b611ae4565b9050919050565b6000819050919050565b61291f826128ea565b61293261292b8261290c565b83546128c7565b8255505050565b6000813561294681612655565b80915050919050565b60008160081b9050919050565b600063ffffff0061296c8461294f565b9350801983169250808416831791505092915050565b600061299d61299861299384611bf9565b611880565b611bf9565b9050919050565b6000819050919050565b6129b782612982565b6129ca6129c3826129a4565b835461295c565b8255505050565b600081356129de81612698565b80915050919050565b60008160201b9050919050565b600067ffffffff00000000612a08846129e7565b9350801983169250808416831791505092915050565b6000612a39612a34612a2f84611c17565b611880565b611c17565b9050919050565b6000819050919050565b612a5382612a1e565b612a66612a5f82612a40565b83546129f4565b8255505050565b60008135612a7a816126db565b80915050919050565b60008160401b9050919050565b600077ffffffffffffffffffffffffffffffff0000000000000000612ab484612a83565b9350801983169250808416831791505092915050565b6000612ae5612ae0612adb84611c36565b611880565b611c36565b9050919050565b6000819050919050565b612aff82612aca565b612b12612b0b82612aec565b8354612a90565b8255505050565b600081016000830180612b2b816128a4565b9050612b378184612916565b505050600081016020830180612b4c81612939565b9050612b5881846129ae565b505050600081016040830180612b6d816129d1565b9050612b798184612a4a565b505050600081016060830180612b8e81612a6d565b9050612b9a8184612af6565b5050505050565b612bab8282612b19565b5050565b600081905092915050565b6000612bc58261192e565b612bcf8185612baf565b9350612bdf81856020860161194a565b80840191505092915050565b6000819050919050565b612c06612c01826118fa565b612beb565b82525050565b6000612c188285612bba565b9150612c248284612bf5565b6020820191508190509392505050565b6000608082019050612c496000830187611904565b612c566020830186611af1565b612c636040830185611904565b612c706060830184611904565b9594505050505056fea26469706673582212204e20478e2e3070a20aa83127753a448e1b78b26fd4b44673d2f1b4027a2cf6be64736f6c634300080d0033", "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101125760003560e01c806306433b1b1461011757806317d7de7c1461013557806324c89a491461015357806326559877146101715780632e0f26251461018d5780632e550693146101ab57806331d98b3f146101db5780633408e4701461020b578063385e05da1461022957806343fa6211146102595780635b38adc71461028957806360846bc6146102b95780636b9c3c7c146102e95780636ebb8cd2146103055780638a1194d31461032357806395f1cf301461035457806396594f66146103705780639ac18b19146103a2578063a3f4df7e146103c0578063c65a53ad146103de578063ccc6fd69146103fc578063d45167d01461042c575b600080fd5b61011f61045c565b60405161012c91906118df565b60405180910390f35b61013d610480565b60405161014a9190611913565b60405180910390f35b61015b6104a8565b60405161016891906119c7565b60405180910390f35b61018b60048036038101906101869190611a84565b6104e1565b005b6101956108af565b6040516101a29190611b00565b60405180910390f35b6101c560048036038101906101c09190611b71565b6108d3565b6040516101d29190611d39565b60405180910390f35b6101f560048036038101906101f09190611d5b565b610a54565b6040516102029190611d97565b60405180910390f35b610213610b77565b6040516102209190611dcb565b60405180910390f35b610243600480360381019061023e9190611b71565b610b7f565b6040516102509190611d39565b60405180910390f35b610273600480360381019061026e9190611d5b565b610d5e565b6040516102809190611e3b565b60405180910390f35b6102a3600480360381019061029e9190611eac565b610e7e565b6040516102b09190611e3b565b60405180910390f35b6102d360048036038101906102ce9190611d5b565b610f89565b6040516102e09190611e3b565b60405180910390f35b61030360048036038101906102fe9190611eac565b611065565b005b61030d611278565b60405161031a9190611dcb565b60405180910390f35b61033d60048036038101906103389190611d5b565b61129c565b60405161034b929190611f08565b60405180910390f35b61036e60048036038101906103699190611f87565b6113c8565b005b61038a60048036038101906103859190611d5b565b611560565b6040516103999392919061204a565b60405180910390f35b6103aa611696565b6040516103b7919061209e565b60405180910390f35b6103c86116ba565b6040516103d5919061210e565b60405180910390f35b6103e66116f3565b6040516103f39190612151565b60405180910390f35b6104166004803603810190610411919061216c565b611717565b6040516104239190611913565b60405180910390f35b61044660048036038101906104419190612219565b61175b565b60405161045391906122a1565b60405180910390f35b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f556d6272656c6c61466565647300000000000000000000000000000000000000905090565b6040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525081565b60007f000000000000000000000000000000000000000000000000000000000000000061ffff16838390501015610544576040517fe246dc6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000061ffff1667ffffffffffffffff811115610584576105836122bc565b5b6040519080825280602002602001820160405280156105b25781602001602082028036833780820191505090505b50905060005b7f000000000000000000000000000000000000000000000000000000000000000061ffff168110156107d75760008060008787858181106105fc576105fb6122eb565b5b9050606002016000016020810190610614919061231a565b888886818110610627576106266122eb565b5b90506060020160200135898987818110610644576106436122eb565b5b905060600201604001359250925092507f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08160001c11156106b1576040517f454ffaa700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601b8360ff16141580156106c95750601c8360ff1614155b15610700576040517f1afa741400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061070e8a85858561175b565b90508073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1610610775576040517f9079f69b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8096508086868151811061078c5761078b6122eb565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508480600101955050505050506105b8565b507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16631d4f9ce0826040518263ffffffff1660e01b81526004016108319190612405565b602060405180830381865afa15801561084e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610872919061245f565b6108a8576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60608282905067ffffffffffffffff8111156108f2576108f16122bc565b5b60405190808252806020026020018201604052801561092b57816020015b610918611818565b8152602001906001900390816109105790505b50905060005b83839050811015610a4d57600080858584818110610952576109516122eb565b5b9050602002013581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681525050828281518110610a3557610a346122eb565b5b60200260200101819052508080600101915050610931565b5092915050565b6000806000808481526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603610b6a576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060600151915050919050565b600046905090565b60608282905067ffffffffffffffff811115610b9e57610b9d6122bc565b5b604051908082528060200260200182016040528015610bd757816020015b610bc4611818565b815260200190600190039081610bbc5790505b50905060005b83839050811015610d5757600080858584818110610bfe57610bfd6122eb565b5b9050602002013581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681525050828281518110610ce157610ce06122eb565b5b60200260200101819052506000828281518110610d0157610d006122eb565b5b60200260200101516040015163ffffffff1603610d4a576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8080600101915050610bdd565b5092915050565b610d66611818565b6000808381526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603610e79576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b610e86611818565b60008383604051602001610e9b9291906124cb565b6040516020818303038152906040528051906020012090506000808281526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505091505092915050565b610f91611818565b6000808381526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815250509050919050565b3073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663e8f98f886040518060400160405280600d81526020017f556d6272656c6c614665656473000000000000000000000000000000000000008152506040518263ffffffff1660e01b815260040161110a919061210e565b602060405180830381865afa158015611127573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114b9190612510565b73ffffffffffffffffffffffffffffffffffffffff1603611198576040517f8c3e700900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600084846040516020016111b09291906124cb565b60405160208183030381529060405280519060200120815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff161480156112285750426203f4807f0000000000000000000000000000000000000000000000000000000000000000611226919061256c565b115b1561125f576040517fcf51b43b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff16ff5b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060008060008581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff16036113b4576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806060015181604001519250925050915091565b838390508686905014611407576040517f0cf7902300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611411610b77565b308888888860405160200161142b96959493929190612820565b60405160208183030381529060405280519060200120905061144e8184846104e1565b60005b85859050811015611556576000888883818110611471576114706122eb565b5b90506020020135905086868381811061148d5761148c6122eb565b5b90506080020160400160208101906114a59190612877565b63ffffffff1660008083815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff161061150e576040517f1251b2f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b868683818110611521576115206122eb565b5b90506080020160008083815260200190815260200160002081816115459190612ba1565b905050818060010192505050611451565b5050505050505050565b6000806000806000808681526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603611679576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806060015181604001518260200151935093509350509193909250565b7f000000000000000000000000000000000000000000000000000000000000000081565b6040518060400160405280600d81526020017f556d6272656c6c6146656564730000000000000000000000000000000000000081525081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000611721610b77565b308686868660405160200161173b96959493929190612820565b604051602081830303815290604052805190602001209050949350505050565b6000806040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250866040516020016117a6929190612c0c565b604051602081830303815290604052805190602001209050600181868686604051600081526020016040526040516117e19493929190612c34565b6020604051602081039080840390855afa158015611803573d6000803e3d6000fd5b50505060206040510351915050949350505050565b6040518060800160405280600060ff168152602001600062ffffff168152602001600063ffffffff16815260200160006fffffffffffffffffffffffffffffffff1681525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006118a56118a061189b84611860565b611880565b611860565b9050919050565b60006118b78261188a565b9050919050565b60006118c9826118ac565b9050919050565b6118d9816118be565b82525050565b60006020820190506118f460008301846118d0565b92915050565b6000819050919050565b61190d816118fa565b82525050565b60006020820190506119286000830184611904565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561196857808201518184015260208101905061194d565b83811115611977576000848401525b50505050565b6000601f19601f8301169050919050565b60006119998261192e565b6119a38185611939565b93506119b381856020860161194a565b6119bc8161197d565b840191505092915050565b600060208201905081810360008301526119e1818461198e565b905092915050565b600080fd5b600080fd5b6119fc816118fa565b8114611a0757600080fd5b50565b600081359050611a19816119f3565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112611a4457611a43611a1f565b5b8235905067ffffffffffffffff811115611a6157611a60611a24565b5b602083019150836060820283011115611a7d57611a7c611a29565b5b9250929050565b600080600060408486031215611a9d57611a9c6119e9565b5b6000611aab86828701611a0a565b935050602084013567ffffffffffffffff811115611acc57611acb6119ee565b5b611ad886828701611a2e565b92509250509250925092565b600060ff82169050919050565b611afa81611ae4565b82525050565b6000602082019050611b156000830184611af1565b92915050565b60008083601f840112611b3157611b30611a1f565b5b8235905067ffffffffffffffff811115611b4e57611b4d611a24565b5b602083019150836020820283011115611b6a57611b69611a29565b5b9250929050565b60008060208385031215611b8857611b876119e9565b5b600083013567ffffffffffffffff811115611ba657611ba56119ee565b5b611bb285828601611b1b565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b611bf381611ae4565b82525050565b600062ffffff82169050919050565b611c1181611bf9565b82525050565b600063ffffffff82169050919050565b611c3081611c17565b82525050565b60006fffffffffffffffffffffffffffffffff82169050919050565b611c5b81611c36565b82525050565b608082016000820151611c776000850182611bea565b506020820151611c8a6020850182611c08565b506040820151611c9d6040850182611c27565b506060820151611cb06060850182611c52565b50505050565b6000611cc28383611c61565b60808301905092915050565b6000602082019050919050565b6000611ce682611bbe565b611cf08185611bc9565b9350611cfb83611bda565b8060005b83811015611d2c578151611d138882611cb6565b9750611d1e83611cce565b925050600181019050611cff565b5085935050505092915050565b60006020820190508181036000830152611d538184611cdb565b905092915050565b600060208284031215611d7157611d706119e9565b5b6000611d7f84828501611a0a565b91505092915050565b611d9181611c36565b82525050565b6000602082019050611dac6000830184611d88565b92915050565b6000819050919050565b611dc581611db2565b82525050565b6000602082019050611de06000830184611dbc565b92915050565b608082016000820151611dfc6000850182611bea565b506020820151611e0f6020850182611c08565b506040820151611e226040850182611c27565b506060820151611e356060850182611c52565b50505050565b6000608082019050611e506000830184611de6565b92915050565b60008083601f840112611e6c57611e6b611a1f565b5b8235905067ffffffffffffffff811115611e8957611e88611a24565b5b602083019150836001820283011115611ea557611ea4611a29565b5b9250929050565b60008060208385031215611ec357611ec26119e9565b5b600083013567ffffffffffffffff811115611ee157611ee06119ee565b5b611eed85828601611e56565b92509250509250929050565b611f0281611c17565b82525050565b6000604082019050611f1d6000830185611d88565b611f2a6020830184611ef9565b9392505050565b60008083601f840112611f4757611f46611a1f565b5b8235905067ffffffffffffffff811115611f6457611f63611a24565b5b602083019150836080820283011115611f8057611f7f611a29565b5b9250929050565b60008060008060008060608789031215611fa457611fa36119e9565b5b600087013567ffffffffffffffff811115611fc257611fc16119ee565b5b611fce89828a01611b1b565b9650965050602087013567ffffffffffffffff811115611ff157611ff06119ee565b5b611ffd89828a01611f31565b9450945050604087013567ffffffffffffffff8111156120205761201f6119ee565b5b61202c89828a01611a2e565b92509250509295509295509295565b61204481611bf9565b82525050565b600060608201905061205f6000830186611d88565b61206c6020830185611ef9565b612079604083018461203b565b949350505050565b600061ffff82169050919050565b61209881612081565b82525050565b60006020820190506120b3600083018461208f565b92915050565b600081519050919050565b600082825260208201905092915050565b60006120e0826120b9565b6120ea81856120c4565b93506120fa81856020860161194a565b6121038161197d565b840191505092915050565b6000602082019050818103600083015261212881846120d5565b905092915050565b600061213b826118ac565b9050919050565b61214b81612130565b82525050565b60006020820190506121666000830184612142565b92915050565b60008060008060408587031215612186576121856119e9565b5b600085013567ffffffffffffffff8111156121a4576121a36119ee565b5b6121b087828801611b1b565b9450945050602085013567ffffffffffffffff8111156121d3576121d26119ee565b5b6121df87828801611f31565b925092505092959194509250565b6121f681611ae4565b811461220157600080fd5b50565b600081359050612213816121ed565b92915050565b60008060008060808587031215612233576122326119e9565b5b600061224187828801611a0a565b945050602061225287828801612204565b935050604061226387828801611a0a565b925050606061227487828801611a0a565b91505092959194509250565b600061228b82611860565b9050919050565b61229b81612280565b82525050565b60006020820190506122b66000830184612292565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156123305761232f6119e9565b5b600061233e84828501612204565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61237c81612280565b82525050565b600061238e8383612373565b60208301905092915050565b6000602082019050919050565b60006123b282612347565b6123bc8185612352565b93506123c783612363565b8060005b838110156123f85781516123df8882612382565b97506123ea8361239a565b9250506001810190506123cb565b5085935050505092915050565b6000602082019050818103600083015261241f81846123a7565b905092915050565b60008115159050919050565b61243c81612427565b811461244757600080fd5b50565b60008151905061245981612433565b92915050565b600060208284031215612475576124746119e9565b5b60006124838482850161244a565b91505092915050565b600081905092915050565b82818337600083830152505050565b60006124b2838561248c565b93506124bf838584612497565b82840190509392505050565b60006124d88284866124a6565b91508190509392505050565b6124ed81612280565b81146124f857600080fd5b50565b60008151905061250a816124e4565b92915050565b600060208284031215612526576125256119e9565b5b6000612534848285016124fb565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061257782611db2565b915061258283611db2565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156125b7576125b661253d565b5b828201905092915050565b600082825260208201905092915050565b600080fd5b60006125e483856125c2565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115612617576126166125d3565b5b602083029250612628838584612497565b82840190509392505050565b6000819050919050565b600061264d6020840184612204565b905092915050565b61265e81611bf9565b811461266957600080fd5b50565b60008135905061267b81612655565b92915050565b6000612690602084018461266c565b905092915050565b6126a181611c17565b81146126ac57600080fd5b50565b6000813590506126be81612698565b92915050565b60006126d360208401846126af565b905092915050565b6126e481611c36565b81146126ef57600080fd5b50565b600081359050612701816126db565b92915050565b600061271660208401846126f2565b905092915050565b6080820161272f600083018361263e565b61273c6000850182611bea565b5061274a6020830183612681565b6127576020850182611c08565b5061276560408301836126c4565b6127726040850182611c27565b506127806060830183612707565b61278d6060850182611c52565b50505050565b600061279f838361271e565b60808301905092915050565b600082905092915050565b6000608082019050919050565b60006127cf8385611bc9565b93506127da82612634565b8060005b85811015612813576127f082846127ab565b6127fa8882612793565b9750612805836127b6565b9250506001810190506127de565b5085925050509392505050565b60006080820190506128356000830189611dbc565b6128426020830188612292565b81810360408301526128558186886125d8565b9050818103606083015261286a8184866127c3565b9050979650505050505050565b60006020828403121561288d5761288c6119e9565b5b600061289b848285016126af565b91505092915050565b600081356128b1816121ed565b80915050919050565b60008160001b9050919050565b600060ff6128d4846128ba565b9350801983169250808416831791505092915050565b60006129056129006128fb84611ae4565b611880565b611ae4565b9050919050565b6000819050919050565b61291f826128ea565b61293261292b8261290c565b83546128c7565b8255505050565b6000813561294681612655565b80915050919050565b60008160081b9050919050565b600063ffffff0061296c8461294f565b9350801983169250808416831791505092915050565b600061299d61299861299384611bf9565b611880565b611bf9565b9050919050565b6000819050919050565b6129b782612982565b6129ca6129c3826129a4565b835461295c565b8255505050565b600081356129de81612698565b80915050919050565b60008160201b9050919050565b600067ffffffff00000000612a08846129e7565b9350801983169250808416831791505092915050565b6000612a39612a34612a2f84611c17565b611880565b611c17565b9050919050565b6000819050919050565b612a5382612a1e565b612a66612a5f82612a40565b83546129f4565b8255505050565b60008135612a7a816126db565b80915050919050565b60008160401b9050919050565b600077ffffffffffffffffffffffffffffffff0000000000000000612ab484612a83565b9350801983169250808416831791505092915050565b6000612ae5612ae0612adb84611c36565b611880565b611c36565b9050919050565b6000819050919050565b612aff82612aca565b612b12612b0b82612aec565b8354612a90565b8255505050565b600081016000830180612b2b816128a4565b9050612b378184612916565b505050600081016020830180612b4c81612939565b9050612b5881846129ae565b505050600081016040830180612b6d816129d1565b9050612b798184612a4a565b505050600081016060830180612b8e81612a6d565b9050612b9a8184612af6565b5050505050565b612bab8282612b19565b5050565b600081905092915050565b6000612bc58261192e565b612bcf8185612baf565b9350612bdf81856020860161194a565b80840191505092915050565b6000819050919050565b612c06612c01826118fa565b612beb565b82525050565b6000612c188285612bba565b9150612c248284612bf5565b6020820191508190509392505050565b6000608082019050612c496000830187611904565b612c566020830186611af1565b612c636040830185611904565b612c706060830184611904565b9594505050505056fea26469706673582212204e20478e2e3070a20aa83127753a448e1b78b26fd4b44673d2f1b4027a2cf6be64736f6c634300080d0033", @@ -858,12 +858,12 @@ "storageLayout": { "storage": [ { - "astId": 4270, + "astId": 4239, "contract": "contracts/onChainFeeds/UmbrellaFeeds.sol:UmbrellaFeeds", "label": "_prices", "offset": 0, "slot": "0", - "type": "t_mapping(t_bytes32,t_struct(PriceData)3396_storage)" + "type": "t_mapping(t_bytes32,t_struct(PriceData)3365_storage)" } ], "types": { @@ -872,19 +872,19 @@ "label": "bytes32", "numberOfBytes": "32" }, - "t_mapping(t_bytes32,t_struct(PriceData)3396_storage)": { + "t_mapping(t_bytes32,t_struct(PriceData)3365_storage)": { "encoding": "mapping", "key": "t_bytes32", "label": "mapping(bytes32 => struct IUmbrellaFeeds.PriceData)", "numberOfBytes": "32", - "value": "t_struct(PriceData)3396_storage" + "value": "t_struct(PriceData)3365_storage" }, - "t_struct(PriceData)3396_storage": { + "t_struct(PriceData)3365_storage": { "encoding": "inplace", "label": "struct IUmbrellaFeeds.PriceData", "members": [ { - "astId": 3386, + "astId": 3355, "contract": "contracts/onChainFeeds/UmbrellaFeeds.sol:UmbrellaFeeds", "label": "data", "offset": 0, @@ -892,7 +892,7 @@ "type": "t_uint8" }, { - "astId": 3389, + "astId": 3358, "contract": "contracts/onChainFeeds/UmbrellaFeeds.sol:UmbrellaFeeds", "label": "heartbeat", "offset": 1, @@ -900,7 +900,7 @@ "type": "t_uint24" }, { - "astId": 3392, + "astId": 3361, "contract": "contracts/onChainFeeds/UmbrellaFeeds.sol:UmbrellaFeeds", "label": "timestamp", "offset": 4, @@ -908,7 +908,7 @@ "type": "t_uint32" }, { - "astId": 3395, + "astId": 3364, "contract": "contracts/onChainFeeds/UmbrellaFeeds.sol:UmbrellaFeeds", "label": "price", "offset": 8, diff --git a/deployments/arbitrum_production/solcInputs/dc68422c0ad35a4fe46d461b096b9383.json b/deployments/arbitrum_production/solcInputs/dc68422c0ad35a4fe46d461b096b9383.json new file mode 100644 index 00000000..43238985 --- /dev/null +++ b/deployments/arbitrum_production/solcInputs/dc68422c0ad35a4fe46d461b096b9383.json @@ -0,0 +1,125 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n }\n _balances[to] += amount;\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n _balances[account] += amount;\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n }\n _totalSupply -= amount;\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Trees proofs.\n *\n * The proofs can be generated using the JavaScript library\n * https://github.com/miguelmota/merkletreejs[merkletreejs].\n * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.\n *\n * See `test/utils/cryptography/MerkleProof.test.js` for some examples.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(\n bytes32[] memory proof,\n bytes32 root,\n bytes32 leaf\n ) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n bytes32 proofElement = proof[i];\n if (computedHash <= proofElement) {\n // Hash(current computed hash + current element of the proof)\n computedHash = _efficientHash(computedHash, proofElement);\n } else {\n // Hash(current element of the proof + current computed hash)\n computedHash = _efficientHash(proofElement, computedHash);\n }\n }\n return computedHash;\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "@umb-network/toolbox/dist/contracts/lib/ValueDecoder.sol": { + "content": "//SPDX-License-Identifier: Unlicensed\npragma solidity >=0.6.8;\n\nlibrary ValueDecoder {\n function toUint(bytes memory _bytes) internal pure returns (uint256 value) {\n assembly {\n value := mload(add(_bytes, 32))\n }\n }\n\n function toUint(bytes32 _bytes) internal pure returns (uint256 value) {\n assembly {\n value := _bytes\n }\n }\n\n function toInt(uint224 u) internal pure returns (int256) {\n int224 i;\n uint224 max = type(uint224).max;\n\n if (u <= (max - 1) / 2) { // positive values\n assembly {\n i := add(u, 0)\n }\n\n return i;\n } else { // negative values\n assembly {\n i := sub(sub(u, max), 1)\n }\n }\n\n return i;\n }\n}\n\n" + }, + "contracts/BaseChain.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\";\nimport \"@umb-network/toolbox/dist/contracts/lib/ValueDecoder.sol\";\n\nimport \"./interfaces/IBaseChainV1.sol\";\nimport \"./interfaces/IStakingBank.sol\";\nimport \"./extensions/Registrable.sol\";\nimport \"./Registry.sol\";\n\nabstract contract BaseChain is Registrable, Ownable {\n using ValueDecoder for bytes;\n using ValueDecoder for uint224;\n using MerkleProof for bytes32[];\n\n /// @param root merkle root for consensus\n /// @param dataTimestamp consensus timestamp\n struct Block {\n bytes32 root;\n uint32 dataTimestamp;\n }\n\n /// @param value FCD value\n /// @param dataTimestamp FCD timestamp\n struct FirstClassData {\n uint224 value;\n uint32 dataTimestamp;\n }\n\n /// @param blocksCountOffset number of all blocks that were generated before switching to this contract\n /// @param sequence is a total number of blocks (consensus rounds) including previous contracts\n /// @param lastTimestamp is a timestamp of last submitted block\n /// @param padding number of seconds that need to pass before new submit will be possible\n /// @param deprecated flag that changes to TRUE on `unregister`, when TRUE submissions are not longer available\n struct ConsensusData {\n uint32 blocksCountOffset;\n uint32 sequence;\n uint32 lastTimestamp;\n uint32 padding;\n bool deprecated;\n }\n\n uint256 constant public VERSION = 2;\n\n bool internal immutable _ALLOW_FOR_MIXED_TYPE; // solhint-disable-line var-name-mixedcase\n\n bytes4 constant private _VERSION_SELECTOR = bytes4(keccak256(\"VERSION()\"));\n\n /// @dev minimal number of signatures required for accepting submission (PoA)\n uint16 internal immutable _REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\n\n ConsensusData internal _consensusData;\n\n bytes constant public ETH_PREFIX = \"\\x19Ethereum Signed Message:\\n32\";\n\n /// @dev block id (consensus ID) => root\n /// consensus ID is at the same time consensus timestamp\n mapping(uint256 => bytes32) public roots;\n\n /// @dev FCD key => FCD data\n mapping(bytes32 => FirstClassData) public fcds;\n\n event LogDeprecation(address indexed deprecator);\n event LogPadding(address indexed executor, uint32 timePadding);\n\n error ArraysDataDoNotMatch();\n error AlreadyDeprecated();\n error AlreadyRegistered();\n error BlockSubmittedToFastOrDataToOld();\n error ContractNotReady();\n error FCDOverflow();\n error InvalidContractType();\n error NoChangeToState();\n error OnlyOwnerOrRegistry();\n error UnregisterFirst();\n\n modifier onlyOwnerOrRegistry () {\n if (msg.sender != address(contractRegistry) && msg.sender != owner()) revert OnlyOwnerOrRegistry();\n _;\n }\n\n /// @param _contractRegistry Registry address\n /// @param _padding required \"space\" between blocks in seconds\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n constructor(\n IRegistry _contractRegistry,\n uint32 _padding,\n uint16 _requiredSignatures,\n bool _allowForMixedType\n ) Registrable(_contractRegistry) {\n _ALLOW_FOR_MIXED_TYPE = _allowForMixedType;\n _REQUIRED_SIGNATURES = _requiredSignatures;\n\n _setPadding(_padding);\n\n BaseChain oldChain = BaseChain(_contractRegistry.getAddress(\"Chain\"));\n\n if (address(oldChain) == address(0)) {\n // if this is first contract in sidechain, then we need to initialise lastTimestamp so submission\n // can be possible\n _consensusData.lastTimestamp = uint32(block.timestamp) - _padding - 1;\n }\n }\n\n /// @dev setter for `padding`\n function setPadding(uint16 _padding) external {\n _setPadding(_padding);\n }\n\n /// @notice if this method needs to be called manually (not from Registry)\n /// it is important to do it as part of tx batch\n /// eg using multisig, we should prepare set of transactions and confirm them all at once\n /// @inheritdoc Registrable\n function register() external override onlyOwnerOrRegistry {\n address oldChain = contractRegistry.getAddress(\"Chain\");\n\n // registration must be done before address in registry is replaced\n if (oldChain == address(this)) revert AlreadyRegistered();\n\n if (oldChain == address(0x0)) {\n return;\n }\n\n _cloneLastDataFromPrevChain(oldChain);\n }\n\n /// @inheritdoc Registrable\n function unregister() external override onlyOwnerOrRegistry {\n // in case we deprecated contract manually, we simply return\n if (_consensusData.deprecated) return;\n\n address newChain = contractRegistry.getAddress(\"Chain\");\n // unregistering must be done after address in registry is replaced\n if (newChain == address(this)) revert UnregisterFirst();\n\n // TODO:\n // I think we need to remove restriction for type (at least once)\n // when we will switch to multichain architecture\n\n if (!_ALLOW_FOR_MIXED_TYPE) {\n // can not be replaced with chain of different type\n if (BaseChain(newChain).isForeign() != this.isForeign()) revert InvalidContractType();\n }\n\n _consensusData.deprecated = true;\n emit LogDeprecation(msg.sender);\n }\n\n /// @notice it allows to deprecate contract manually\n /// Only new Registry calls `unregister()` where we set deprecated to true\n /// In old Registries we don't have this feature, so in order to safely redeploy new Chain\n /// we will have to first deprecate current contract manually, then register new contract\n function deprecate() external onlyOwnerOrRegistry {\n if (_consensusData.deprecated) revert AlreadyDeprecated();\n\n _consensusData.deprecated = true;\n emit LogDeprecation(msg.sender);\n }\n\n /// @dev getter for `_consensusData`\n function getConsensusData() external view returns (ConsensusData memory) {\n return _consensusData;\n }\n\n /// @dev number of blocks (consensus rounds) saved in this contract\n function blocksCount() external view returns (uint256) {\n return _consensusData.sequence - _consensusData.blocksCountOffset;\n }\n\n function blocksCountOffset() external view returns (uint32) {\n return _consensusData.blocksCountOffset;\n }\n\n function lastBlockId() external view returns (uint256) {\n return _consensusData.lastTimestamp;\n }\n\n /// @return TRUE if contract is ForeignChain, FALSE otherwise\n function isForeign() external pure virtual returns (bool);\n\n /// @inheritdoc Registrable\n function getName() external pure override returns (bytes32) {\n return \"Chain\";\n }\n\n /// @param _affidavit root and FCDs hashed together\n /// @param _v part of signature\n /// @param _r part of signature\n /// @param _s part of signature\n /// @return signer address\n function recoverSigner(bytes32 _affidavit, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _affidavit));\n return ecrecover(hash, _v, _r, _s);\n }\n\n /// @param _blockId ID of submitted block\n /// @return block data (root + timestamp)\n function blocks(uint256 _blockId) external view returns (Block memory) {\n return Block(roots[_blockId], uint32(_blockId));\n }\n\n /// @return current block ID\n /// please note, that current ID is not the same as last ID, current means that once padding pass,\n /// ID will switch to next one and it will be pointing to empty submit until submit for that ID is done\n function getBlockId() external view returns (uint32) {\n if (_consensusData.lastTimestamp == 0) return 0;\n\n return getBlockIdAtTimestamp(block.timestamp);\n }\n\n function requiredSignatures() external view returns (uint16) {\n return _REQUIRED_SIGNATURES;\n }\n\n /// @dev calculates block ID for provided timestamp\n /// this function does not works for past timestamps\n /// @param _timestamp current or future timestamp\n /// @return block ID for provided timestamp\n function getBlockIdAtTimestamp(uint256 _timestamp) virtual public view returns (uint32) {\n ConsensusData memory data = _consensusData;\n\n unchecked {\n // we can't overflow because we adding two `uint32`\n if (data.lastTimestamp + data.padding < _timestamp) {\n return uint32(_timestamp);\n }\n }\n\n return data.lastTimestamp;\n }\n\n /// @return last submitted block ID, please note, that on deployment, when there is no submission for this contract\n /// block for last ID will be available in previous contract\n function getLatestBlockId() virtual public view returns (uint32) {\n return _consensusData.lastTimestamp;\n }\n\n /// @dev verifies if the leaf is valid leaf for merkle tree\n /// @param _proof merkle proof for merkle tree\n /// @param _root merkle root\n /// @param _leaf leaf hash\n /// @return TRUE if `_leaf` is valid, FALSE otherwise\n function verifyProof(bytes32[] memory _proof, bytes32 _root, bytes32 _leaf) public pure returns (bool) {\n if (_root == bytes32(0)) {\n return false;\n }\n\n return _proof.verify(_root, _leaf);\n }\n\n /// @dev creates leaf hash, that has is used in merkle tree\n /// @param _key key under which we store the value\n /// @param _value value itself as bytes\n /// @return leaf hash\n function hashLeaf(bytes memory _key, bytes memory _value) public pure returns (bytes32) {\n return keccak256(abi.encodePacked(_key, _value));\n }\n\n /// @dev verifies, if provided key-value pair was part of consensus\n /// @param _blockId consensus ID for which we doing a check\n /// @param _proof merkle proof for pair\n /// @param _key pair key\n /// @param _value pair value\n /// @return TRUE if key-value par was part of consensus, FALSE otherwise\n function verifyProofForBlock(\n uint256 _blockId,\n bytes32[] memory _proof,\n bytes memory _key,\n bytes memory _value\n )\n public\n view\n returns (bool)\n {\n return _proof.verify(roots[_blockId], keccak256(abi.encodePacked(_key, _value)));\n }\n\n /// @dev this is helper method, that extracts one merkle proof from many hashed provided as bytes\n /// @param _data many hashes as bytes\n /// @param _offset this is starting point for extraction\n /// @param _items how many hashes to extract\n /// @return merkle proof (array of bytes32 hashes)\n function bytesToBytes32Array(\n bytes memory _data,\n uint256 _offset,\n uint256 _items\n )\n public\n pure\n returns (bytes32[] memory)\n {\n bytes32[] memory dataList = new bytes32[](_items);\n\n // we can unchecked because we working only with `i` and `_offset`\n // in case of wrong `_offset` it will throw\n unchecked {\n for (uint256 i = 0; i < _items; i++) {\n bytes32 temp;\n uint256 idx = (i + 1 + _offset) * 32;\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n temp := mload(add(_data, idx))\n }\n\n dataList[i] = temp;\n }\n }\n\n return (dataList);\n }\n\n /// @dev batch method for data verification\n /// @param _blockIds consensus IDs for which we doing a checks\n /// @param _proofs merkle proofs for all pair, sequence of hashes provided as bytes\n /// @param _proofItemsCounter array of counters, each counter tells how many hashes proof for each leaf has\n /// @param _leaves array of merkle leaves\n /// @return results array of verification results, TRUE if leaf is part of consensus, FALSE otherwise\n function verifyProofs(\n uint32[] memory _blockIds,\n bytes memory _proofs,\n uint256[] memory _proofItemsCounter,\n bytes32[] memory _leaves\n )\n public\n view\n returns (bool[] memory results)\n {\n results = new bool[](_leaves.length);\n uint256 offset = 0;\n\n for (uint256 i = 0; i < _leaves.length;) {\n results[i] = bytesToBytes32Array(_proofs, offset, _proofItemsCounter[i]).verify(\n roots[_blockIds[i]], _leaves[i]\n );\n\n unchecked {\n // we can uncheck because it will not overflow in a lifetime, and if someone provide invalid counter\n // we verification will not be valid (or we throw because of invalid memory access)\n offset += _proofItemsCounter[i];\n // we can uncheck because `i` will not overflow in a lifetime\n i++;\n }\n }\n }\n\n /// @param _blockId consensus ID\n /// @return root for provided consensus ID\n function getBlockRoot(uint32 _blockId) external view returns (bytes32) {\n return roots[_blockId];\n }\n\n /// @param _blockId consensus ID\n /// @return timestamp for provided consensus ID\n function getBlockTimestamp(uint32 _blockId) external view returns (uint32) {\n return roots[_blockId] == bytes32(0) ? 0 : _blockId;\n }\n\n /// @dev batch getter for FCDs\n /// @param _keys FCDs keys to fetch\n /// @return values array of FCDs values\n /// @return timestamps array of FCDs timestamps\n function getCurrentValues(bytes32[] calldata _keys)\n external\n view\n returns (uint256[] memory values, uint32[] memory timestamps)\n {\n timestamps = new uint32[](_keys.length);\n values = new uint256[](_keys.length);\n\n for (uint i=0; i<_keys.length;) {\n FirstClassData storage numericFCD = fcds[_keys[i]];\n values[i] = uint256(numericFCD.value);\n timestamps[i] = numericFCD.dataTimestamp;\n\n unchecked {\n // we can uncheck because `i` will not overflow in a lifetime\n i++;\n }\n }\n }\n\n /// @dev getter for single FCD value\n /// @param _key FCD key\n /// @return value FCD value\n /// @return timestamp FCD timestamp\n function getCurrentValue(bytes32 _key) external view returns (uint256 value, uint256 timestamp) {\n FirstClassData storage numericFCD = fcds[_key];\n return (uint256(numericFCD.value), numericFCD.dataTimestamp);\n }\n\n /// @dev getter for single FCD value in case its type is `int`\n /// @param _key FCD key\n /// @return value FCD value\n /// @return timestamp FCD timestamp\n function getCurrentIntValue(bytes32 _key) external view returns (int256 value, uint256 timestamp) {\n FirstClassData storage numericFCD = fcds[_key];\n return (numericFCD.value.toInt(), numericFCD.dataTimestamp);\n }\n\n function _setPadding(uint32 _padding) internal onlyOwner {\n if (_consensusData.padding == _padding) revert NoChangeToState();\n\n _consensusData.padding = _padding;\n emit LogPadding(msg.sender, _padding);\n }\n\n /// @dev we cloning last block time, because we will need reference point for next submissions\n function _cloneLastDataFromPrevChain(address _prevChain) internal {\n (bool success, bytes memory v) = _prevChain.staticcall(abi.encode(_VERSION_SELECTOR));\n uint256 prevVersion = success ? abi.decode(v, (uint256)) : 1;\n\n if (prevVersion == 1) {\n uint32 latestId = IBaseChainV1(address(_prevChain)).getLatestBlockId();\n _consensusData.lastTimestamp = IBaseChainV1(address(_prevChain)).getBlockTimestamp(latestId);\n\n // +1 because getLatestBlockId subtracts 1\n // +1 because it might be situation when tx is already in progress in old contract\n // and old contract do not have deprecated flag\n _consensusData.sequence = latestId + 2;\n _consensusData.blocksCountOffset = latestId + 2;\n } else { // VERSION 2\n // with new Registry, we have register/unregister methods\n // Chain will be deprecated, so there is no need to do \"+1\" as in old version\n // TODO what with current Registries??\n // we need a way to make it deprecated!\n ConsensusData memory data = BaseChain(_prevChain).getConsensusData();\n\n _consensusData.sequence = data.sequence;\n _consensusData.blocksCountOffset = data.sequence;\n _consensusData.lastTimestamp = data.lastTimestamp;\n }\n }\n}\n" + }, + "contracts/Chain.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./BaseChain.sol\";\n\ncontract Chain is BaseChain {\n IStakingBank public immutable stakingBank;\n\n event LogMint(address indexed minter, uint256 blockId, uint256 staked, uint256 power);\n event LogVoter(uint256 indexed blockId, address indexed voter, uint256 vote);\n\n error NotEnoughSignatures();\n error SignaturesOutOfOrder();\n\n /// @param _contractRegistry Registry address\n /// @param _padding required \"space\" between blocks in seconds\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n /// @param _allowForMixedType we have two \"types\" of Chain: HomeChain and ForeignChain, when we redeploying\n /// we don't want to mix up them, so we checking, if new Chain has the same type as current one.\n /// However, when we will be switching from one homechain to another one, we have to allow for this mixing up.\n /// This flag will tell contract, if this is the case.\n constructor(\n IRegistry _contractRegistry,\n uint32 _padding,\n uint16 _requiredSignatures,\n bool _allowForMixedType\n ) BaseChain(_contractRegistry, _padding, _requiredSignatures, _allowForMixedType) {\n stakingBank = IStakingBank(_contractRegistry.requireAndGetAddress(\"StakingBank\"));\n }\n\n /// @dev method for submitting consensus data\n /// @param _dataTimestamp consensus timestamp, this is time for all data in merkle tree including FCDs\n /// @param _root merkle root\n /// @param _keys FCDs keys\n /// @param _values FCDs values\n /// @param _v array of `v` part of validators signatures\n /// @param _r array of `r` part of validators signatures\n /// @param _s array of `s` part of validators signatures\n // solhint-disable-next-line function-max-lines, code-complexity\n function submit(\n uint32 _dataTimestamp,\n bytes32 _root,\n bytes32[] memory _keys,\n uint256[] memory _values,\n uint8[] memory _v,\n bytes32[] memory _r,\n bytes32[] memory _s\n ) external {\n // below two checks are only for pretty errors, so we can safe gas and allow for raw revert\n // if (_keys.length != _values.length) revert ArraysDataDoNotMatch();\n // if (_v.length != _r.length || _r.length != _s.length) revert ArraysDataDoNotMatch();\n\n _verifySubmitTimestampAndIncSequence(_dataTimestamp);\n\n // we can't expect minter will have exactly the same timestamp\n // but for sure we can demand not to be off by a lot, that's why +3sec\n // temporary remove this condition, because recently on ropsten we see cases when minter/node\n // can be even 100sec behind\n // require(_dataTimestamp <= block.timestamp + 3,\n // string(abi.encodePacked(\"oh, so you can predict the future:\", _dataTimestamp - block.timestamp + 48)));\n\n bytes memory testimony = abi.encodePacked(_dataTimestamp, _root);\n\n for (uint256 i = 0; i < _keys.length;) {\n if (uint224(_values[i]) != _values[i]) revert FCDOverflow();\n\n fcds[_keys[i]] = FirstClassData(uint224(_values[i]), _dataTimestamp);\n testimony = abi.encodePacked(testimony, _keys[i], _values[i]);\n\n unchecked {\n // we can't pass enough data to overflow\n i++;\n }\n }\n\n uint256 signatures = 0;\n uint256 power = 0;\n //uint256 staked = stakingBank.totalSupply();\n bytes32 affidavit = keccak256(testimony);\n\n address prevSigner = address(0x0);\n\n for (uint256 i; i < _v.length;) {\n address signer = recoverSigner(affidavit, _v[i], _r[i], _s[i]);\n uint256 balance = stakingBank.balanceOf(signer);\n\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\n\n prevSigner = signer;\n\n if (balance == 0) {\n unchecked { i++; }\n continue;\n }\n\n signatures++;\n emit LogVoter(uint256(_dataTimestamp), signer, balance);\n\n unchecked {\n // we can't overflow because that means token overflowed\n // and even if we do, we will get lower power\n power += balance;\n i++;\n }\n }\n\n if (signatures < _REQUIRED_SIGNATURES) revert NotEnoughSignatures();\n\n emit LogMint(msg.sender, _dataTimestamp, stakingBank.totalSupply(), power);\n\n // TODO remember to protect against flash loans when DPoS will be in place\n // we turn on power once we have DPoS in action, we have PoA now\n // require(power * 100 / staked >= 66, \"not enough power was gathered\");\n\n roots[_dataTimestamp] = _root;\n _consensusData.lastTimestamp = _dataTimestamp;\n }\n\n /// @inheritdoc BaseChain\n function isForeign() external pure virtual override returns (bool) {\n return false;\n }\n\n /// @dev helper method that returns all important data about current state of contract\n /// @return blockNumber `block.number`\n /// @return timePadding `this.padding`\n /// @return lastDataTimestamp timestamp for last submitted consensus\n /// @return lastId ID of last submitted consensus\n /// @return nextLeader leader for `block.timestamp + 1`\n /// @return nextBlockId block ID for `block.timestamp + padding`\n /// @return validators array of all validators addresses\n /// @return powers array of all validators powers\n /// @return locations array of all validators locations\n /// @return staked total UMB staked by validators\n /// @return minSignatures `this.requiredSignatures`\n function getStatus() external view virtual returns(\n uint256 blockNumber,\n uint32 timePadding,\n uint32 lastDataTimestamp,\n uint32 lastId,\n address nextLeader,\n uint32 nextBlockId,\n address[] memory validators,\n uint256[] memory powers,\n string[] memory locations,\n uint256 staked,\n uint16 minSignatures\n ) {\n ConsensusData memory data = _consensusData;\n\n blockNumber = block.number;\n timePadding = data.padding;\n lastId = data.lastTimestamp;\n lastDataTimestamp = lastId;\n minSignatures = _REQUIRED_SIGNATURES;\n\n staked = stakingBank.totalSupply();\n uint256 numberOfValidators = stakingBank.getNumberOfValidators();\n powers = new uint256[](numberOfValidators);\n validators = new address[](numberOfValidators);\n locations = new string[](numberOfValidators);\n\n for (uint256 i = 0; i < numberOfValidators;) {\n validators[i] = stakingBank.addresses(i);\n (, locations[i]) = stakingBank.validators(validators[i]);\n powers[i] = stakingBank.balanceOf(validators[i]);\n\n unchecked {\n // we will run out of gas before overflow happen\n i++;\n }\n }\n\n unchecked {\n // we will not overflow with timestamp in a lifetime\n nextBlockId = lastId + data.padding + 1;\n\n nextLeader = numberOfValidators > 0\n // we will not overflow with timestamp in a lifetime\n ? validators[getLeaderIndex(numberOfValidators, block.timestamp + 1)]\n : address(0);\n }\n }\n\n /// @return address of leader for next second\n function getNextLeaderAddress() external view returns (address) {\n return getLeaderAddressAtTime(block.timestamp + 1);\n }\n\n /// @return address of current leader\n function getLeaderAddress() external view returns (address) {\n return getLeaderAddressAtTime(block.timestamp);\n }\n\n /// @param _numberOfValidators total number of validators\n /// @param _timestamp timestamp for which you want to calculate index\n /// @return leader index, use it for StakingBank.addresses[index] to fetch leader address\n function getLeaderIndex(uint256 _numberOfValidators, uint256 _timestamp) public view virtual returns (uint256) {\n ConsensusData memory data = _consensusData;\n\n unchecked {\n // we will not overflow on `timestamp` and `padding` in a life time\n // timePadding + 1 => because padding is a space between blocks,\n // so next round starts on first block after padding\n // TODO will it work for off-chain??\n uint256 validatorIndex = data.sequence + (_timestamp - data.lastTimestamp) / (data.padding + 1);\n\n return validatorIndex % _numberOfValidators;\n }\n }\n\n // @todo - properly handled non-enabled validators, newly added validators, and validators with low stake\n /// @param _timestamp timestamp for which you want to calculate leader address\n /// @return leader address for provider timestamp\n function getLeaderAddressAtTime(uint256 _timestamp) public view virtual returns (address) {\n uint256 numberOfValidators = stakingBank.getNumberOfValidators();\n\n if (numberOfValidators == 0) {\n return address(0x0);\n }\n\n uint256 validatorIndex = getLeaderIndex(numberOfValidators, _timestamp);\n\n return stakingBank.addresses(validatorIndex);\n }\n\n /// @dev we had stack too deep in `submit` so this method was created as a solution\n // we increasing `_consensusData.sequence` here so we don't have to read sequence again in other place\n function _verifySubmitTimestampAndIncSequence(uint256 _dataTimestamp) internal {\n ConsensusData memory data = _consensusData;\n\n // `data.lastTimestamp` must be setup either on deployment\n // or via cloning from previous contract\n if (data.lastTimestamp == 0) revert ContractNotReady();\n\n unchecked {\n // we will not overflow with timestamp and padding in a life time\n if (data.lastTimestamp + data.padding >= _dataTimestamp) revert BlockSubmittedToFastOrDataToOld();\n }\n\n unchecked {\n // we will not overflow in a life time\n _consensusData.sequence = uint32(data.sequence + 1);\n }\n }\n}\n" + }, + "contracts/extensions/Registrable.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\n/// @dev Any contract that we want to register in ContractRegistry, must inherit from Registrable\nabstract contract Registrable {\n IRegistry public immutable contractRegistry;\n\n modifier onlyFromContract(address _msgSender, bytes32 _contractName) {\n require(\n contractRegistry.getAddress(_contractName) == _msgSender,\n string(abi.encodePacked(\"caller is not \", _contractName))\n );\n _;\n }\n\n modifier withRegistrySetUp() {\n require(address(contractRegistry) != address(0x0), \"_registry is empty\");\n _;\n }\n\n constructor(IRegistry _contractRegistry) {\n require(address(_contractRegistry) != address(0x0), \"_registry is empty\");\n contractRegistry = _contractRegistry;\n }\n\n /// @dev this method will be called as a first method in registration process when old contract will be replaced\n /// when called, old contract address is still in registry\n function register() virtual external;\n\n /// @dev this method will be called as a last method in registration process when old contract will be replaced\n /// when called, new contract address is already in registry\n function unregister() virtual external;\n\n /// @return contract name as bytes32\n function getName() virtual external pure returns (bytes32);\n\n /// @dev helper method for fetching StakingBank address\n function stakingBankContract() public view returns (IStakingBank) {\n return IStakingBank(contractRegistry.requireAndGetAddress(\"StakingBank\"));\n }\n\n /// @dev helper method for fetching UMB address\n function tokenContract() public view withRegistrySetUp returns (ERC20) {\n return ERC20(contractRegistry.requireAndGetAddress(\"UMB\"));\n }\n}\n" + }, + "contracts/ForeignChain.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./Chain.sol\";\n\n/// @dev contract for foreign chains\ncontract ForeignChain is Chain {\n error NotSupported();\n\n /// @param _contractRegistry Registry address\n /// @param _padding required \"space\" between blocks in seconds\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n constructor(\n IRegistry _contractRegistry,\n uint32 _padding,\n uint16 _requiredSignatures,\n bool _allowForMixedType\n ) Chain(_contractRegistry, _padding, _requiredSignatures, _allowForMixedType) {\n // no additional configuration needed\n }\n\n /// @inheritdoc BaseChain\n function isForeign() external pure override returns (bool) {\n return true;\n }\n\n /// @inheritdoc Chain\n /// @notice this method is made to be compatible with MasterChain, but it does not return full data eg validators\n /// data will be missing.\n /// @return blockNumber `block.number`\n /// @return timePadding `this.padding`\n /// @return lastDataTimestamp timestamp for last submitted consensus\n /// @return lastId ID of last submitted consensus\n /// @return nextLeader will be always address(0)\n /// @return nextBlockId block ID for `block.timestamp + padding`\n /// @return validators array will be always empty\n /// @return powers array will be always empty\n /// @return locations array will be always empty\n /// @return staked total UMB staked by validators\n /// @return minSignatures `this.requiredSignatures`\n function getStatus() external view override returns(\n uint256 blockNumber,\n uint32 timePadding,\n uint32 lastDataTimestamp,\n uint32 lastId,\n address nextLeader,\n uint32 nextBlockId,\n address[] memory validators,\n uint256[] memory powers,\n string[] memory locations,\n uint256 staked,\n uint16 minSignatures\n ) {\n ConsensusData memory data = _consensusData;\n\n blockNumber = block.number;\n timePadding = data.padding;\n lastId = data.lastTimestamp;\n lastDataTimestamp = lastId;\n minSignatures = _REQUIRED_SIGNATURES;\n\n staked = stakingBank.totalSupply();\n uint256 numberOfValidators = 0;\n powers = new uint256[](numberOfValidators);\n validators = new address[](numberOfValidators);\n locations = new string[](numberOfValidators);\n nextLeader = address(0);\n\n unchecked {\n // we will not overflow with timestamp in a lifetime\n nextBlockId = lastId + data.padding + 1;\n }\n }\n\n function getLeaderIndex(uint256, uint256) public pure override returns (uint256) {\n revert NotSupported();\n }\n\n function getLeaderAddressAtTime(uint256) public pure override returns (address) {\n revert NotSupported();\n }\n}\n" + }, + "contracts/interfaces/IBaseChainV1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IBaseChainV1 {\n /// @dev number of blocks (consensus rounds) saved in this contract\n function blocksCount() external returns (uint32);\n\n /// @dev number of all blocks that were generated before switching to this contract\n /// please note, that there might be a gap of one block when we switching from old to new contract\n /// see constructor for details\n function blocksCountOffset() external returns (uint32);\n\n function getLatestBlockId() external view returns (uint32);\n\n function getBlockTimestamp(uint32 _blockId) external view returns (uint32);\n\n function getStatus() external view returns (\n uint256 blockNumber,\n uint16 timePadding,\n uint32 lastDataTimestamp,\n uint32 lastId,\n uint32 nextBlockId\n );\n}\n" + }, + "contracts/interfaces/IRegistry.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\n\ninterface IRegistry {\n event LogRegistered(address indexed destination, bytes32 name);\n\n /// @dev imports new contract addresses and override old addresses, if they exist under provided name\n /// This method can be used for contracts that for some reason do not have `getName` method\n /// @param _names array of contract names that we want to register\n /// @param _destinations array of contract addresses\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external;\n\n /// @dev imports new contracts and override old addresses, if they exist.\n /// Names of contracts are fetched directly from each contract by calling `getName`\n /// @param _destinations array of contract addresses\n function importContracts(address[] calldata _destinations) external;\n\n /// @dev this method ensure, that old and new contract is aware of it state in registry\n /// Note: BSC registry does not have this method. This method was introduced in later stage.\n /// @param _newContract address of contract that will replace old one\n function atomicUpdate(address _newContract) external;\n\n /// @dev similar to `getAddress` but throws when contract name not exists\n /// @param name contract name\n /// @return contract address registered under provided name or throws, if does not exists\n function requireAndGetAddress(bytes32 name) external view returns (address);\n\n /// @param name contract name in a form of bytes32\n /// @return contract address registered under provided name\n function getAddress(bytes32 name) external view returns (address);\n\n /// @param _name contract name\n /// @return contract address assigned to the name or address(0) if not exists\n function getAddressByString(string memory _name) external view returns (address);\n\n /// @dev helper method that converts string to bytes32,\n /// you can use to to generate contract name\n function stringToBytes32(string memory _string) external pure returns (bytes32 result);\n}\n" + }, + "contracts/interfaces/IStakingBank.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IStakingBank is IERC20 {\n /// @param id address of validator wallet\n /// @param location URL of the validator API\n struct Validator {\n address id;\n string location;\n }\n\n event LogValidatorRegistered(address indexed id);\n event LogValidatorUpdated(address indexed id);\n event LogValidatorRemoved(address indexed id);\n event LogMinAmountForStake(uint256 minAmountForStake);\n\n /// @dev setter for `minAmountForStake`\n function setMinAmountForStake(uint256 _minAmountForStake) external;\n\n /// @dev allows to stake `token` by validators\n /// Validator needs to approve StakingBank beforehand\n /// @param _value amount of tokens to stake\n function stake(uint256 _value) external;\n\n /// @dev notification about approval from `_from` address on UMB token\n /// Staking bank will stake max approved amount from `_from` address\n /// @param _from address which approved token spend for IStakingBank\n function receiveApproval(address _from) external returns (bool success);\n\n /// @dev withdraws stake tokens\n /// it throws, when balance will be less than required minimum for stake\n /// to withdraw all use `exit`\n function withdraw(uint256 _value) external returns (bool success);\n\n /// @dev unstake and withdraw all tokens\n function exit() external returns (bool success);\n\n /// @dev creates (register) new validator\n /// @param _id validator address\n /// @param _location location URL of the validator API\n function create(address _id, string calldata _location) external;\n\n /// @dev removes validator\n /// @param _id validator wallet\n function remove(address _id) external;\n\n /// @dev updates validator location\n /// @param _id validator wallet\n /// @param _location new validator URL\n function update(address _id, string calldata _location) external;\n\n /// @return total number of registered validators (with and without balance)\n function getNumberOfValidators() external view returns (uint256);\n\n /// @dev gets validator address for provided index\n /// @param _ix index in array of list of all validators wallets\n function addresses(uint256 _ix) external view returns (address);\n\n /// @param _id address of validator\n /// @return id address of validator\n /// @return location URL of validator\n function validators(address _id) external view returns (address id, string memory location);\n}\n" + }, + "contracts/interfaces/IStakingBankStatic.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./IStakingBank.sol\";\n\n\ninterface IStakingBankStatic is IStakingBank {\n /// @param _validators array of validators addresses to verify\n /// @return TRUE when all validators are valid, FALSE otherwise\n function verifyValidators(address[] calldata _validators) external view returns (bool);\n}\n" + }, + "contracts/interfaces/IUmbrellaFeeds.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IUmbrellaFeeds {\n struct PriceData {\n /// @dev this is placeholder, that can be used for some additional data\n /// atm of creating this smart contract, it is only used as marker for removed data (when == type(uint8).max)\n uint8 data;\n /// @dev heartbeat: how often price data will be refreshed in case price stay flat\n uint24 heartbeat;\n /// @dev timestamp: price time, at this time validators run consensus\n uint32 timestamp;\n /// @dev price\n uint128 price;\n }\n\n struct Signature {\n uint8 v;\n bytes32 r;\n bytes32 s;\n }\n\n /// @dev method for submitting consensus data\n /// @param _priceKeys array of keys for `_priceDatas`\n /// @param _priceDatas PriceData signed by validators\n /// @param _signatures validators signatures\n function update(\n bytes32[] calldata _priceKeys,\n PriceData[] calldata _priceDatas,\n Signature[] calldata _signatures\n ) external;\n\n /// @dev it will return array of price datas for provided `_keys`\n /// In case ony of feed does not exist, fallback call will be executed for that feed.\n /// @notice If data for any key not exists, function will revert. Use `getManyPriceDataRaw` method if you don't\n /// want revert.\n /// @param _keys array of feed keys\n /// @return data PriceData array\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data);\n\n /// @dev same as getManyPriceData() but does not revert on empty data.\n /// @notice This method does no revert if some data does not exists.\n /// Check `data.timestamp` to see if price exist, if it is 0, then it does not exist.\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data);\n\n /// @dev this is main endpoint for reading feeds.\n /// In case timestamp is empty (that means there is no data), contract will revert.\n /// If you do not need whole data from `PriceData` struct, you can save some gas by using other view methods that\n /// returns just what you need.\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return data full PriceData struct\n function getPriceData(bytes32 _key) external view returns (PriceData memory data);\n\n /// @notice reader for mapping\n /// @param _key hash of feed name\n /// @return data full PriceData struct\n function prices(bytes32 _key) external view returns (PriceData memory data);\n\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return price\n function getPrice(bytes32 _key) external view returns (uint128 price);\n\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return price\n /// @return timestamp\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp);\n\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return price\n /// @return timestamp\n /// @return heartbeat\n function getPriceTimestampHeartbeat(bytes32 _key)\n external\n view\n returns (uint128 price, uint32 timestamp, uint24 heartbeat);\n\n /// @dev This method should be used only for Layer2 as it is more gas consuming than others views.\n /// @notice It does not revert on empty data.\n /// @param _name string feed name\n /// @return data PriceData\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data);\n\n /// @dev decimals for prices stored in this contract\n function DECIMALS() external view returns (uint8); // solhint-disable-line func-name-mixedcase\n}\n" + }, + "contracts/interfaces/StakingBankStaticNotSupported.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./IStakingBank.sol\";\n\nabstract contract StakingBankStaticNotSupported is IStakingBank {\n error NotSupported();\n\n function create(address, string calldata) external pure {\n revert NotSupported();\n }\n\n function update(address, string calldata) external pure {\n revert NotSupported();\n }\n\n function remove(address) external pure {\n revert NotSupported();\n }\n\n function transfer(address, uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function transferFrom(address, address, uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function receiveApproval(address) external pure returns (bool) {\n revert NotSupported();\n }\n\n function allowance(address, address) external pure returns (uint256) {\n revert NotSupported();\n }\n\n function approve(address, uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function stake(uint256) external pure {\n revert NotSupported();\n }\n\n function withdraw(uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function exit() external pure returns (bool) {\n revert NotSupported();\n }\n\n function setMinAmountForStake(uint256) external pure {\n revert NotSupported();\n }\n}\n" + }, + "contracts/mock/Distributor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport \"../Registry.sol\";\n\ncontract Distributor is Ownable {\n address[] public recipients;\n uint256 public bottomLimit = 5e17;\n uint256 public topLimit = 1e18;\n\n constructor(address[] memory _recipients) {\n recipients = _recipients;\n }\n\n receive() external payable {\n distribute();\n }\n\n function setLimits(uint256 _bottom, uint256 _top) external onlyOwner {\n bottomLimit = _bottom;\n topLimit = _top;\n }\n\n function withdraw() external {\n uint balance = address(this).balance;\n uint buffer = recipients.length * (topLimit - bottomLimit);\n\n if (balance > buffer) {\n payable(owner()).transfer(balance - buffer);\n }\n }\n\n function addRecipients(address[] calldata _recipients) external onlyOwner {\n for (uint256 i = 0; i < _recipients.length; i++) {\n recipients.push(_recipients[i]);\n }\n }\n\n function removeRecipient(address _recipient) external onlyOwner {\n for (uint256 i = 0; i < recipients.length; i++) {\n if (recipients[i] == _recipient) {\n recipients[i] = recipients[recipients.length - 1];\n recipients.pop();\n return;\n }\n }\n }\n\n function recipientsCount() external view returns (uint256) {\n return recipients.length;\n }\n\n function allRecipients() external view returns (address[] memory) {\n return recipients;\n }\n\n function getName() external pure returns (bytes32) {\n return \"Distributor\";\n }\n\n function distribute() public {\n uint256 limit = bottomLimit;\n uint256 top = topLimit;\n uint256 count = recipients.length;\n uint256 totalBalance = address(this).balance;\n\n for (uint256 i = 0; i < count; i++) {\n uint256 balance = recipients[i].balance;\n\n if (balance > limit) {\n continue;\n }\n\n uint256 amount = top - balance > totalBalance ? totalBalance : top - balance;\n\n if (amount > 0) {\n payable(recipients[i]).transfer(amount);\n totalBalance -= amount;\n }\n }\n }\n}\n" + }, + "contracts/mock/LimitedMintingToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\ncontract LimitedMintingToken is ERC20, Ownable {\n struct MintData {\n uint256 dailyAllowance;\n mapping (address => uint256) lastMintTimestamp;\n mapping (address => uint256) todaysMintedAmount;\n }\n\n MintData public mintData;\n\n constructor(string memory _name, string memory _symbol, uint256 _dailyAllowance) ERC20(_name, _symbol) {\n mintData.dailyAllowance = _dailyAllowance;\n }\n\n function mint(address _holder, uint256 _amount) external {\n MintData storage data = mintData;\n\n (uint256 limit, bool fullLimit) = _currentLimit(data);\n\n require(limit > 0, \"This address already claimed the maximum daily amount\");\n\n uint256 lastTimestamp = data.lastMintTimestamp[msg.sender];\n uint256 mintedAmount = data.todaysMintedAmount[msg.sender];\n\n uint256 amount = _amount > limit ? limit : _amount;\n data.lastMintTimestamp[msg.sender] = fullLimit ? block.timestamp : lastTimestamp;\n data.todaysMintedAmount[msg.sender] = fullLimit ? amount : mintedAmount + amount;\n\n _mint(_holder, amount);\n }\n\n function mintApproveAndStake(IStakingBank _stakingBank, address _holder, uint256 _amount) external {\n _mint(_holder, _amount);\n _approve(_holder, address(_stakingBank), _amount);\n _stakingBank.receiveApproval(_holder);\n }\n\n function getDailyAllowance() external view returns (uint256) {\n return mintData.dailyAllowance;\n }\n\n function getName() external pure returns (bytes32) {\n return \"UMB\";\n }\n\n function setDailyAllowance(uint256 newDailyAllowance) public onlyOwner {\n MintData storage data = mintData;\n data.dailyAllowance = newDailyAllowance;\n }\n\n function _currentLimit(MintData storage data) internal view returns (uint256 limit, bool fullLimit) {\n uint256 lastMint = data.lastMintTimestamp[msg.sender];\n fullLimit = block.timestamp - lastMint >= 24 hours;\n\n uint256 usedLimit = data.todaysMintedAmount[msg.sender];\n\n limit = fullLimit ? data.dailyAllowance : data.dailyAllowance - usedLimit;\n }\n}\n" + }, + "contracts/mock/Token.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\n// please remember this is our dummy token!\n// it will be replaced by proper DPoS solution in future\ncontract Token is ERC20 {\n constructor(\n string memory _name,\n string memory _symbol) ERC20(_name, _symbol) {\n }\n\n function mint(address _holder, uint256 _amount) external {\n _mint(_holder, _amount);\n }\n\n function mintApproveAndStake(IStakingBank _stakingBank, address _holder, uint256 _amount) external {\n _mint(_holder, _amount);\n _approve(_holder, address(_stakingBank), _amount);\n _stakingBank.receiveApproval(_holder);\n }\n\n function getName() external pure returns (bytes32) {\n return \"UMB\";\n }\n}\n" + }, + "contracts/onChainFeeds/UmbrellaFeeds.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/IUmbrellaFeeds.sol\";\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IStakingBankStatic.sol\";\n\n/// @dev Main contract for all on-chain data.\n/// Check `UmbrellaFeedsReader` to see how to integrate.\n///\n/// @notice This contract can be destroyed and replaced with new one (with new address).\n/// For best gas efficiency you should pick one of two ways of integration:\n/// 1. make `UmbrellaFeeds` immutable and use fallback in case of selfdestruct. After new deployment, it is recommended\n/// to update address to avoid fallback and reduce gas cost to minimum. In long run this is most efficient solution,\n/// better than any proxy.\n/// 2. always check newest `UmbrellaFeeds` via `Regostry` and fallback will not be needed.\ncontract UmbrellaFeeds is IUmbrellaFeeds {\n bytes constant public ETH_PREFIX = \"\\x19Ethereum Signed Message:\\n32\";\n string constant public NAME = \"UmbrellaFeeds\";\n\n /// @dev deployment time, used for protect for unintentional destroy\n uint256 public immutable DEPLOYED_AT; // solhint-disable-line var-name-mixedcase\n\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\n /// resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev StakingBank contract where list of validators is stored\n IStakingBankStatic public immutable STAKING_BANK; // solhint-disable-line var-name-mixedcase\n\n /// @dev minimal number of signatures required for accepting price submission (PoA)\n uint16 public immutable REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\n\n /// @dev decimals for prices stored in this contract\n uint8 public immutable DECIMALS; // solhint-disable-line var-name-mixedcase\n\n /// @notice map of all prices stored in this contract, key for map is hash of feed name\n /// eg for \"ETH-USD\" feed, key will be hash(\"ETH-USD\")\n mapping (bytes32 => PriceData) private _prices;\n\n error ArraysDataDoNotMatch();\n error FeedNotExist();\n error NotEnoughSignatures();\n error InvalidSigner();\n error InvalidRequiredSignatures();\n error SignaturesOutOfOrder();\n error ECDSAInvalidSignatureS();\n error ECDSAInvalidSignatureV();\n error OldData();\n error ContractInUse();\n error ContractNotInitialised();\n\n /// @param _contractRegistry Registry address\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n /// @param _decimals decimals for prices stored in this contract\n constructor(\n IRegistry _contractRegistry,\n uint16 _requiredSignatures,\n uint8 _decimals\n ) {\n if (_requiredSignatures == 0) revert InvalidRequiredSignatures();\n\n REGISTRY = _contractRegistry;\n REQUIRED_SIGNATURES = _requiredSignatures;\n STAKING_BANK = IStakingBankStatic(_contractRegistry.requireAndGetAddress(\"StakingBank\"));\n DECIMALS = _decimals;\n DEPLOYED_AT = block.timestamp;\n }\n\n /// @dev destroys old contract\n /// there is sanity check that prevents abuse of destroy method\n /// @param _name string feed key to verify, that contract was initialised\n function destroy(string calldata _name) external {\n if (REGISTRY.getAddressByString(NAME) == address(this)) revert ContractInUse();\n\n if (_prices[keccak256(abi.encodePacked(_name))].timestamp == 0 && DEPLOYED_AT + 3 days > block.timestamp) {\n revert ContractNotInitialised();\n }\n\n selfdestruct(payable(msg.sender));\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function update(\n bytes32[] calldata _priceKeys,\n PriceData[] calldata _priceDatas,\n Signature[] calldata _signatures\n ) external {\n if (_priceKeys.length != _priceDatas.length) revert ArraysDataDoNotMatch();\n\n bytes32 priceDataHash = keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n verifySignatures(priceDataHash, _signatures);\n\n uint256 i;\n\n while (i < _priceDatas.length) {\n bytes32 priceKey = _priceKeys[i];\n\n // we do not allow for older prices\n // at the same time it prevents from reusing signatures\n if (_prices[priceKey].timestamp >= _priceDatas[i].timestamp) revert OldData();\n\n _prices[priceKey] = _priceDatas[i];\n\n // atm there is no need for events, so in order to save gas, we do not emit any\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n if (data[i].timestamp == 0) revert FeedNotExist();\n\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function prices(bytes32 _key) external view returns (PriceData memory data) {\n data = _prices[_key];\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceData(bytes32 _key) external view returns (PriceData memory data) {\n data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPrice(bytes32 _key) external view returns (uint128 price) {\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return data.price;\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp) {\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp);\n }\n\n function getPriceTimestampHeartbeat(bytes32 _key)\n external\n view\n returns (uint128 price, uint32 timestamp, uint24 heartbeat)\n {\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp, data.heartbeat);\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data) {\n bytes32 key = keccak256(abi.encodePacked(_name));\n data = _prices[key];\n }\n\n /// @dev helper method for QA purposes\n /// @return hash of data that are signed by validators (keys and priced data)\n function hashData(bytes32[] calldata _priceKeys, PriceData[] calldata _priceDatas)\n external\n view\n returns (bytes32)\n {\n return keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n }\n\n /// @param _hash hash of signed data\n /// @param _signatures array of validators signatures\n function verifySignatures(bytes32 _hash, Signature[] calldata _signatures) public view {\n address prevSigner = address(0x0);\n\n if (_signatures.length < REQUIRED_SIGNATURES) revert NotEnoughSignatures();\n\n address[] memory validators = new address[](REQUIRED_SIGNATURES);\n\n // to save gas we check only required number of signatures\n // case, where you can have part of signatures invalid but still enough valid in total is not supported\n for (uint256 i; i < REQUIRED_SIGNATURES;) {\n (uint8 v, bytes32 r, bytes32 s) = (_signatures[i].v, _signatures[i].r, _signatures[i].s);\n\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n revert ECDSAInvalidSignatureS();\n }\n\n if (uint8(v) != 27 && uint8(v) != 28) revert ECDSAInvalidSignatureV();\n\n address signer = recoverSigner(_hash, v, r, s);\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\n\n // because we check only required number of signatures, any invalid one will cause revert\n prevSigner = signer;\n validators[i] = signer;\n\n unchecked { i++; }\n }\n\n // bulk verification can optimise gas when we have 5 or more validators\n if (!STAKING_BANK.verifyValidators(validators)) revert InvalidSigner();\n }\n\n function getChainId() public view returns (uint256 id) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n id := chainid()\n }\n }\n\n /// @param _hash hashed of data\n /// @param _v part of signature\n /// @param _r part of signature\n /// @param _s part of signature\n /// @return signer address\n function recoverSigner(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _hash));\n return ecrecover(hash, _v, _r, _s);\n }\n\n /// @dev to follow Registrable interface\n function getName() public pure returns (bytes32) {\n return \"UmbrellaFeeds\";\n }\n}\n" + }, + "contracts/onChainFeeds/UmbrellaFeedsReader.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IUmbrellaFeeds.sol\";\n\n/// @dev This is optional price reader for just one feed.\n/// It comes with chanilink interface that makes migration process easier.\n/// For maximum gas optimisation it is recommended to use UmbrellaFeeds directly - simply follow this contract as\n/// a guide for integration.\n///\n/// This contract has build in fallback feature in case, `UmbrellaFeeds` will be replaced by newer contract.\n/// Fallback is transparent for the user, no additional setup is needed.\n///\n/// How fallback feature works? If data for provided key is empty (when UmbrellaFeeds was destroyed and replaced),\n/// contract will execute following procedure:\n/// 1. if data is empty, contract will check if there is new registered contract with requested data\n/// 2. if data is found in new contract it will be returned\n/// 3. if there is no data or there is no new contract tx will revert.\ncontract UmbrellaFeedsReader {\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\n /// resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev contract where all the feeds are stored\n address public immutable UMBRELLA_FEEDS; // solhint-disable-line var-name-mixedcase\n\n /// @dev key (hash of string key), under which feed is being stored\n bytes32 public immutable KEY; // solhint-disable-line var-name-mixedcase\n\n /// @dev string representation of feed key (feed name)\n string public description;\n\n /// @dev decimals for feed\n uint8 internal immutable _DECIMALS; // solhint-disable-line var-name-mixedcase\n\n error EmptyAddress();\n error FeedNotExist();\n\n /// @param _registry IRegistry address\n /// @param _umbrellaFeeds UmbrellaFeeds address\n /// @param _key price data key (before hashing)\n constructor(IRegistry _registry, IUmbrellaFeeds _umbrellaFeeds, string memory _key) {\n if (address(_registry) == address(0)) revert EmptyAddress();\n\n REGISTRY = _registry;\n UMBRELLA_FEEDS = address(_umbrellaFeeds);\n description = _key;\n _DECIMALS = _umbrellaFeeds.DECIMALS();\n\n bytes32 hash = keccak256(abi.encodePacked(_key));\n KEY = hash;\n\n // sanity check\n _umbrellaFeeds.getPriceData(hash);\n }\n\n /// @dev decimals for feed\n function decimals() external view returns (uint8) {\n return _DECIMALS;\n }\n\n /// @dev this method follows chainlink interface for easy migration, NOTE: not all returned data are covered!\n /// latestRoundData() raise exception when there is no data, instead of returning unset values,\n /// which could be misinterpreted as actual reported values.\n /// It DOES NOT raise when data is outdated (based on heartbeat and timestamp).\n /// @notice You can save some gas by doing call directly to `UMBRELLA_FEEDS` contract.\n /// @return uint80 originally `roundId`, not in use, always 0\n /// @return answer price\n /// @return uint256 originally `startedAt`, not in use, always 0\n /// @return updatedAt last timestamp data was updated\n /// @return uint80 originally `answeredInRound` not in use, always 0\n function latestRoundData()\n external\n view\n returns (\n uint80 /* roundId */,\n int256 answer,\n uint256 /* startedAt */,\n uint256 updatedAt,\n uint80 /* answeredInRound */\n )\n {\n IUmbrellaFeeds.PriceData memory priceData = _getPriceDataRaw();\n\n if (priceData.timestamp == 0) {\n priceData = _fallbackCall();\n }\n\n return (0, int256(uint256(priceData.price)), 0, priceData.timestamp, 0);\n }\n\n /// @dev this is main endpoint for reading feed. Feed is read from UmbrellaFeeds contract using hardcoded `KEY`.\n /// In case timestamp is empty (that means there is no data), contract will execute fallback call.\n /// @notice revert on empty data\n function getPriceData() external view returns (IUmbrellaFeeds.PriceData memory priceData) {\n priceData = _getPriceDataRaw();\n\n if (priceData.timestamp == 0) {\n priceData = _fallbackCall();\n }\n }\n\n /// @dev same as `getPriceData` but does not revert when no data\n function getPriceDataRaw() external view returns (IUmbrellaFeeds.PriceData memory priceData) {\n priceData = _getPriceDataRaw();\n\n if (priceData.timestamp == 0) {\n return _fallbackCallRaw();\n }\n }\n\n /// @dev same as `getPriceData` but does not revert when no data\n function _getPriceDataRaw() internal view returns (IUmbrellaFeeds.PriceData memory priceData) {\n (bool success, bytes memory data) = UMBRELLA_FEEDS.staticcall(\n abi.encodeWithSelector(IUmbrellaFeeds.prices.selector, KEY)\n );\n\n if (success && data.length != 0) {\n priceData = abi.decode(data, (IUmbrellaFeeds.PriceData));\n }\n }\n\n /// @dev it will revert on empty data\n function _fallbackCall() internal view returns (IUmbrellaFeeds.PriceData memory data) {\n address umbrellaFeeds = REGISTRY.getAddressByString(\"UmbrellaFeeds\");\n\n // if contract was NOT updated, fallback is not needed, data does not exist - revert\n if (umbrellaFeeds == UMBRELLA_FEEDS) revert FeedNotExist();\n\n data = IUmbrellaFeeds(umbrellaFeeds).getPriceData(KEY);\n }\n\n /// @dev it will not revert on empty data\n function _fallbackCallRaw() internal view returns (IUmbrellaFeeds.PriceData memory data) {\n address umbrellaFeeds = REGISTRY.getAddressByString(\"UmbrellaFeeds\");\n\n // if contract was updated, we do fallback\n if (umbrellaFeeds != UMBRELLA_FEEDS) {\n data = IUmbrellaFeeds(umbrellaFeeds).prices(KEY);\n }\n }\n}\n" + }, + "contracts/onChainFeeds/UmbrellaFeedsReaderFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\nimport \"./UmbrellaFeedsReader.sol\";\n\n/// @notice Factory to deploy UmbrellaFeedsReader contract\ncontract UmbrellaFeedsReaderFactory {\n /// @dev Registry contract where list of all addresses is stored. Used to resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev list of all readers\n mapping (bytes32 => UmbrellaFeedsReader) public readers;\n\n event NewUmbrellaFeedsReader(UmbrellaFeedsReader indexed umbrellaFeedsReader, string feedName);\n\n error EmptyAddress();\n\n constructor(IRegistry _registry) {\n if (address(_registry) == address(0)) revert EmptyAddress();\n\n REGISTRY = _registry;\n }\n\n /// @dev Method to deploy new UmbrellaFeedsReader for particular key.\n /// This deployment is optional and it can be done by anyone who needs it.\n /// Reader can be used to simplify migration from Chainlink to Umbrella.\n ///\n /// Check UmbrellaFeedsReader docs for more details.\n ///\n /// We not using minimal proxy because it does not allow for immutable variables.\n /// @param _feedName string Feed name that is registered in UmbrellaFeeds\n /// @return reader UmbrellaFeedsReader contract address, in case anyone wants to use it from Layer1\n function deploy(string memory _feedName) external returns (UmbrellaFeedsReader reader) {\n reader = deployed(_feedName);\n IUmbrellaFeeds umbrellaFeeds = IUmbrellaFeeds(REGISTRY.getAddressByString(\"UmbrellaFeeds\"));\n\n // if UmbrellaFeeds contract is up to date, there is no need to redeploy\n if (address(reader) != address(0) && address(reader.UMBRELLA_FEEDS()) == address(umbrellaFeeds)) {\n return reader;\n }\n\n reader = new UmbrellaFeedsReader(REGISTRY, umbrellaFeeds, _feedName);\n readers[hash(_feedName)] = reader;\n\n emit NewUmbrellaFeedsReader(reader, _feedName);\n }\n\n function deployed(string memory _feedName) public view returns (UmbrellaFeedsReader) {\n return readers[hash(_feedName)];\n }\n\n function hash(string memory _feedName) public pure returns (bytes32) {\n return keccak256(abi.encodePacked(_feedName));\n }\n\n /// @dev to follow Registrable interface\n function getName() public pure returns (bytes32) {\n return \"UmbrellaFeedsReaderFactory\";\n }\n}\n" + }, + "contracts/onChainFeeds/zk-link/UmbrellaFeeds.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../../interfaces/IUmbrellaFeeds.sol\";\nimport \"../../interfaces/IRegistry.sol\";\nimport \"../../interfaces/IStakingBankStatic.sol\";\n\n/// @dev Main contract for all on-chain data.\n/// Check `UmbrellaFeedsReader` to see how to integrate.\n///\n/// @notice This contract can be destroyed and replaced with new one (with new address).\n/// For best gas efficiency you should pick one of two ways of integration:\n/// 1. make `UmbrellaFeeds` immutable and use fallback in case of selfdestruct. After new deployment, it is recommended\n/// to update address to avoid fallback and reduce gas cost to minimum. In long run this is most efficient solution,\n/// better than any proxy.\n/// 2. always check newest `UmbrellaFeeds` via `Regostry` and fallback will not be needed.\ncontract UmbrellaFeeds is IUmbrellaFeeds {\n bytes constant public ETH_PREFIX = \"\\x19Ethereum Signed Message:\\n32\";\n string constant public NAME = \"UmbrellaFeeds\";\n\n /// @dev deployment time, used for protect for unintentional destroy\n uint256 public immutable DEPLOYED_AT; // solhint-disable-line var-name-mixedcase\n\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\n /// resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev StakingBank contract where list of validators is stored\n IStakingBankStatic public immutable STAKING_BANK; // solhint-disable-line var-name-mixedcase\n\n /// @dev minimal number of signatures required for accepting price submission (PoA)\n uint16 public immutable REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\n\n /// @dev decimals for prices stored in this contract\n uint8 public immutable DECIMALS; // solhint-disable-line var-name-mixedcase\n\n /// @dev in case selfdestruct is not supported, this flag will make sure contract is not usable anymore\n bool public disabled;\n\n /// @notice map of all prices stored in this contract, key for map is hash of feed name\n /// eg for \"ETH-USD\" feed, key will be hash(\"ETH-USD\")\n mapping (bytes32 => PriceData) private _prices;\n\n error SelfDestruct();\n error ArraysDataDoNotMatch();\n error FeedNotExist();\n error NotEnoughSignatures();\n error InvalidSigner();\n error InvalidRequiredSignatures();\n error SignaturesOutOfOrder();\n error ECDSAInvalidSignatureS();\n error ECDSAInvalidSignatureV();\n error OldData();\n error ContractInUse();\n error ContractNotInitialised();\n\n /// @param _contractRegistry Registry address\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n /// @param _decimals decimals for prices stored in this contract\n constructor(\n IRegistry _contractRegistry,\n uint16 _requiredSignatures,\n uint8 _decimals\n ) {\n if (_requiredSignatures == 0) revert InvalidRequiredSignatures();\n\n REGISTRY = _contractRegistry;\n REQUIRED_SIGNATURES = _requiredSignatures;\n STAKING_BANK = IStakingBankStatic(_contractRegistry.requireAndGetAddress(\"StakingBank\"));\n DECIMALS = _decimals;\n DEPLOYED_AT = block.timestamp;\n }\n\n /// @dev destroys old contract\n /// there is sanity check that prevents abuse of destroy method\n /// @param _name string feed key to verify, that contract was initialised\n function destroy(string calldata _name) external {\n if (REGISTRY.getAddressByString(NAME) == address(this)) revert ContractInUse();\n\n if (_prices[keccak256(abi.encodePacked(_name))].timestamp == 0 && DEPLOYED_AT + 3 days > block.timestamp) {\n revert ContractNotInitialised();\n }\n\n disabled = true;\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function update(\n bytes32[] calldata _priceKeys,\n PriceData[] calldata _priceDatas,\n Signature[] calldata _signatures\n ) external {\n if (disabled) revert SelfDestruct();\n if (_priceKeys.length != _priceDatas.length) revert ArraysDataDoNotMatch();\n\n bytes32 priceDataHash = keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n verifySignatures(priceDataHash, _signatures);\n\n uint256 i;\n\n while (i < _priceDatas.length) {\n bytes32 priceKey = _priceKeys[i];\n\n // we do not allow for older prices\n // at the same time it prevents from reusing signatures\n if (_prices[priceKey].timestamp >= _priceDatas[i].timestamp) revert OldData();\n\n _prices[priceKey] = _priceDatas[i];\n\n // atm there is no need for events, so in order to save gas, we do not emit any\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n if (disabled) revert SelfDestruct();\n\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n if (data[i].timestamp == 0) revert FeedNotExist();\n\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n if (disabled) revert SelfDestruct();\n\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function prices(bytes32 _key) external view returns (PriceData memory data) {\n if (disabled) revert SelfDestruct();\n\n data = _prices[_key];\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceData(bytes32 _key) external view returns (PriceData memory data) {\n if (disabled) revert SelfDestruct();\n\n data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPrice(bytes32 _key) external view returns (uint128 price) {\n if (disabled) revert SelfDestruct();\n\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return data.price;\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp) {\n if (disabled) revert SelfDestruct();\n\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp);\n }\n\n function getPriceTimestampHeartbeat(bytes32 _key)\n external\n view\n returns (uint128 price, uint32 timestamp, uint24 heartbeat)\n {\n if (disabled) revert SelfDestruct();\n\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp, data.heartbeat);\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data) {\n if (disabled) revert SelfDestruct();\n\n bytes32 key = keccak256(abi.encodePacked(_name));\n data = _prices[key];\n }\n\n /// @dev helper method for QA purposes\n /// @return hash of data that are signed by validators (keys and priced data)\n function hashData(bytes32[] calldata _priceKeys, PriceData[] calldata _priceDatas)\n external\n view\n returns (bytes32)\n {\n return keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n }\n\n /// @param _hash hash of signed data\n /// @param _signatures array of validators signatures\n function verifySignatures(bytes32 _hash, Signature[] calldata _signatures) public view {\n address prevSigner = address(0x0);\n\n if (_signatures.length < REQUIRED_SIGNATURES) revert NotEnoughSignatures();\n\n address[] memory validators = new address[](REQUIRED_SIGNATURES);\n\n // to save gas we check only required number of signatures\n // case, where you can have part of signatures invalid but still enough valid in total is not supported\n for (uint256 i; i < REQUIRED_SIGNATURES;) {\n (uint8 v, bytes32 r, bytes32 s) = (_signatures[i].v, _signatures[i].r, _signatures[i].s);\n\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n revert ECDSAInvalidSignatureS();\n }\n\n if (uint8(v) != 27 && uint8(v) != 28) revert ECDSAInvalidSignatureV();\n\n address signer = recoverSigner(_hash, v, r, s);\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\n\n // because we check only required number of signatures, any invalid one will cause revert\n prevSigner = signer;\n validators[i] = signer;\n\n unchecked { i++; }\n }\n\n // bulk verification can optimise gas when we have 5 or more validators\n if (!STAKING_BANK.verifyValidators(validators)) revert InvalidSigner();\n }\n\n function getChainId() public view returns (uint256 id) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n id := chainid()\n }\n }\n\n /// @param _hash hashed of data\n /// @param _v part of signature\n /// @param _r part of signature\n /// @param _s part of signature\n /// @return signer address\n function recoverSigner(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _hash));\n return ecrecover(hash, _v, _r, _s);\n }\n\n /// @dev to follow Registrable interface\n function getName() public pure returns (bytes32) {\n return \"UmbrellaFeeds\";\n }\n}\n" + }, + "contracts/Registry.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\n// Inheritance\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport \"./extensions/Registrable.sol\";\nimport \"./interfaces/IRegistry.sol\";\n\n/// @dev contracts registry\n/// protocol uses this registry to fetch current contract addresses\ncontract Registry is IRegistry, Ownable {\n /// name => contract address\n mapping(bytes32 => address) public registry;\n\n\n error NameNotRegistered();\n error ArraysDataDoNotMatch();\n\n /// @inheritdoc IRegistry\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external onlyOwner {\n if (_names.length != _destinations.length) revert ArraysDataDoNotMatch();\n\n for (uint i = 0; i < _names.length;) {\n registry[_names[i]] = _destinations[i];\n emit LogRegistered(_destinations[i], _names[i]);\n\n unchecked {\n i++;\n }\n }\n }\n\n /// @inheritdoc IRegistry\n function importContracts(address[] calldata _destinations) external onlyOwner {\n for (uint i = 0; i < _destinations.length;) {\n bytes32 name = Registrable(_destinations[i]).getName();\n registry[name] = _destinations[i];\n emit LogRegistered(_destinations[i], name);\n\n unchecked {\n i++;\n }\n }\n }\n\n /// @inheritdoc IRegistry\n function atomicUpdate(address _newContract) external onlyOwner {\n Registrable(_newContract).register();\n\n bytes32 name = Registrable(_newContract).getName();\n address oldContract = registry[name];\n registry[name] = _newContract;\n\n Registrable(oldContract).unregister();\n\n emit LogRegistered(_newContract, name);\n }\n\n /// @inheritdoc IRegistry\n function requireAndGetAddress(bytes32 name) external view returns (address) {\n address _foundAddress = registry[name];\n if (_foundAddress == address(0)) revert NameNotRegistered();\n\n return _foundAddress;\n }\n\n /// @inheritdoc IRegistry\n function getAddress(bytes32 _bytes) external view returns (address) {\n return registry[_bytes];\n }\n\n /// @inheritdoc IRegistry\n function getAddressByString(string memory _name) public view returns (address) {\n return registry[stringToBytes32(_name)];\n }\n\n /// @inheritdoc IRegistry\n function stringToBytes32(string memory _string) public pure returns (bytes32 result) {\n bytes memory tempEmptyStringTest = bytes(_string);\n\n if (tempEmptyStringTest.length == 0) {\n return 0x0;\n }\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n result := mload(add(_string, 32))\n }\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStatic.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/StakingBankStaticNotSupported.sol\";\n\n/// @dev Because we are using PoA in UMB oracle, staked balance does not matter. What's matter is, if signer is\n/// validator or not. In this case we can optimise `StakingBank` and make it static for better gas performance.\nabstract contract StakingBankStatic is StakingBankStaticNotSupported {\n uint256 public constant ONE = 1e18;\n\n uint256 public immutable NUMBER_OF_VALIDATORS; // solhint-disable-line var-name-mixedcase\n uint256 public immutable TOTAL_SUPPLY; // solhint-disable-line var-name-mixedcase\n\n constructor(uint256 _validatorsCount) {\n NUMBER_OF_VALIDATORS = _validatorsCount;\n TOTAL_SUPPLY = _validatorsCount * ONE;\n\n _assertValidSetup(_validatorsCount);\n }\n\n function balances(address _validator) external view returns (uint256) {\n return _isValidator(_validator) ? ONE : 0;\n }\n\n function verifyValidators(address[] calldata _validators) external view returns (bool) {\n for (uint256 i; i < _validators.length;) {\n if (!_isValidator(_validators[i])) return false;\n unchecked { i++; }\n }\n\n return true;\n }\n\n function getNumberOfValidators() external view returns (uint256) {\n return NUMBER_OF_VALIDATORS;\n }\n\n function getAddresses() external view returns (address[] memory) {\n return _addresses();\n }\n\n function getBalances() external view returns (uint256[] memory allBalances) {\n allBalances = new uint256[](NUMBER_OF_VALIDATORS);\n\n for (uint256 i; i < NUMBER_OF_VALIDATORS;) {\n allBalances[i] = ONE;\n\n unchecked {\n // we will not have enough data to overflow\n i++;\n }\n }\n }\n\n function addresses(uint256 _ix) external view returns (address) {\n return _addresses()[_ix];\n }\n\n function validators(address _id) external view virtual returns (address id, string memory location);\n\n /// @dev to follow ERC20 interface\n function balanceOf(address _account) external view returns (uint256) {\n return _isValidator(_account) ? ONE : 0;\n }\n\n /// @dev to follow ERC20 interface\n function totalSupply() external view returns (uint256) {\n return TOTAL_SUPPLY;\n }\n\n /// @dev to follow Registrable interface\n function getName() external pure returns (bytes32) {\n return \"StakingBank\";\n }\n\n /// @dev to follow Registrable interface\n function register() external pure {\n // there are no requirements atm\n }\n\n /// @dev to follow Registrable interface\n function unregister() external pure {\n // there are no requirements atm\n }\n\n function _addresses() internal view virtual returns (address[] memory);\n\n function _isValidator(address _validator) internal view virtual returns (bool);\n\n function _assertValidSetup(uint256 _validatorsCount) internal view virtual{\n address[] memory list = _addresses();\n require(list.length == _validatorsCount);\n\n for (uint256 i; i < _validatorsCount;) {\n require(_isValidator(list[i]));\n\n unchecked { i ++; }\n }\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticCI.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticCI is StakingBankStatic {\n // 0x87630b2d1de0fbd5044eb6891b3d9d98c34c8d310c852f98550ba774480e47cc\n address public constant VALIDATOR_0 = 0x2fFd013AaA7B5a7DA93336C2251075202b33FB2B;\n // 0x3f1e8b94c70206bf816c1ed0b15ad98bdf225ae4c6e7e4eee6cdbcf706fda2ae\n address public constant VALIDATOR_1 = 0x43158ea338Ff13D0bDa0c3EB969B9EA5a624E7Cc;\n // 0x5da6b84117504d06b5dcd52b990d76965d2882f4e5852eb610bc76e4209b10d7\n address public constant VALIDATOR_2 = 0x9Fd8DD0627b9A32399Fd115c4725C7e17BC40e6d;\n // 0x1e5012671de3332ad0b43661984e94ab0e405bffddc9d3e863055040bab354b8\n address public constant VALIDATOR_3 = 0xa3F3659E469b7aE0b249546338DEdc0b684edB05;\n // 0x0edc1e35ea7701ddac703286674e79f04addbf5d2f6162fabc19d39bd3dc6662\n address public constant VALIDATOR_4 = 0xB98A954B9036DF144d685E910bfbAEC6B33A8d11;\n // 0x23c601ae397441f3ef6f1075dcb0031ff17fb079837beadaf3c84d96c6f3e569\n address public constant VALIDATOR_5 = 0xE5904695748fe4A84b40b3fc79De2277660BD1D3;\n\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.ci.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.ci.umb.network\");\n if (_id == VALIDATOR_2) return (_id, \"https://validator3.ci.umb.network\");\n if (_id == VALIDATOR_3) return (_id, \"https://validator4.ci.umb.network\");\n if (_id == VALIDATOR_4) return (_id, \"https://validator5.ci.umb.network\");\n if (_id == VALIDATOR_5) return (_id, \"https://validator6.ci.umb.network\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n list[2] = VALIDATOR_2;\n list[3] = VALIDATOR_3;\n list[4] = VALIDATOR_4;\n list[5] = VALIDATOR_5;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0\n || _validator == VALIDATOR_1\n || _validator == VALIDATOR_2\n || _validator == VALIDATOR_3\n || _validator == VALIDATOR_4\n || _validator == VALIDATOR_5\n );\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticDev.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticDev is StakingBankStatic {\n address public constant VALIDATOR_0 = 0xDc3eBc37DA53A644D67E5E3b5BA4EEF88D969d5C;\n address public constant VALIDATOR_1 = 0x998cb7821e605cC16b6174e7C50E19ADb2Dd2fB0;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.dev.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.dev.umb.network\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0 || _validator == VALIDATOR_1);\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticLocal.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticLocal is StakingBankStatic {\n address public constant VALIDATOR_0 = 0xeAD9C93b79Ae7C1591b1FB5323BD777E86e150d4;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"localhost\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0);\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticProd.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\ncontract StakingBankStaticProd is StakingBankStatic {\n address public constant VALIDATOR_0 = 0x977Ba523420110e230643B772Fe9cF955e11dA7B;\n address public constant VALIDATOR_1 = 0xe2422b23e52bc13ebA04d7FbB9F332Deb43360fB;\n\n // external order is based on validators submits on AVAX for Apr 2023\n address public constant VALIDATOR_2 = 0x57F404aD75e371c1A539589C1eFCA12e0C6980AD;\n address public constant VALIDATOR_3 = 0xD56C6A4f64E0bD70260472d1DB6Cf5825858CB0d;\n address public constant VALIDATOR_4 = 0x93FdcAB283b0BcAc48157590af482E1CFd6af6aC;\n address public constant VALIDATOR_5 = 0xCd733E06B06083d52fC5867E8E3432aA5c103A38;\n address public constant VALIDATOR_6 = 0x42e210b110c6aa49CdfA7ceF1444Aa4719653111;\n address public constant VALIDATOR_7 = 0x501731c6a69803a53Ec6c3e12f293c247cE1092B;\n address public constant VALIDATOR_8 = 0x8bF9661F1b247522C75DD0FE84355aD2EfF27144;\n address public constant VALIDATOR_9 = 0x281754Ab58391A478B7aA4E7f39991CfB41118c4;\n address public constant VALIDATOR_10 = 0x57A51D5BDcE188c2295fCA3b4687475a54E65A02;\n address public constant VALIDATOR_11 = 0x2F85824B2B38F179E451988670935d315b5b9692;\n address public constant VALIDATOR_12 = 0xA7241994267682de4dE7Ef62f52dc2C783d1784B;\n address public constant VALIDATOR_13 = 0x6eEd457C20603EDAE50C3A112CAA1a9425321bD0;\n address public constant VALIDATOR_14 = 0xC5a7650c2725a7B6A39f15cb9FbffC7af357AFeb;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n // solhint-disable-next-line code-complexity\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.umb.network\");\n if (_id == VALIDATOR_2) return (_id, \"https://umbrella.artemahr.tech\");\n if (_id == VALIDATOR_3) return (_id, \"https://umb.vtabsolutions.com:3030\");\n if (_id == VALIDATOR_4) return (_id, \"https://umbrella.crazywhale.es\");\n if (_id == VALIDATOR_5) return (_id, \"https://umbrella-node.gateomega.com\");\n if (_id == VALIDATOR_6) return (_id, \"https://umb.anorak.technology\");\n if (_id == VALIDATOR_7) return (_id, \"https://umbrella.validator.infstones.io\");\n if (_id == VALIDATOR_8) return (_id, \"https://umb.hashkey.cloud\");\n if (_id == VALIDATOR_9) return (_id, \"http://umbrella.staking4all.org:3000\");\n if (_id == VALIDATOR_10) return (_id, \"http://5.161.78.230:3000\");\n if (_id == VALIDATOR_11) return (_id, \"https://umb-api.staking.rocks\");\n if (_id == VALIDATOR_12) return (_id, \"https://rpc.urbanhq.net\");\n if (_id == VALIDATOR_13) return (_id, \"https://umbrella-node.ankastake.com\");\n if (_id == VALIDATOR_14) return (_id, \"https://umbrella.tchambrella.com\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n list[2] = VALIDATOR_2;\n list[3] = VALIDATOR_3;\n list[4] = VALIDATOR_4;\n list[5] = VALIDATOR_5;\n list[6] = VALIDATOR_6;\n list[7] = VALIDATOR_7;\n list[8] = VALIDATOR_8;\n list[9] = VALIDATOR_9;\n list[10] = VALIDATOR_10;\n list[11] = VALIDATOR_11;\n list[12] = VALIDATOR_12;\n list[13] = VALIDATOR_13;\n list[14] = VALIDATOR_14;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (\n _validator == VALIDATOR_0\n || _validator == VALIDATOR_1\n || _validator == VALIDATOR_2\n || _validator == VALIDATOR_3\n || _validator == VALIDATOR_4\n || _validator == VALIDATOR_5\n || _validator == VALIDATOR_6\n || _validator == VALIDATOR_7\n || _validator == VALIDATOR_8\n || _validator == VALIDATOR_9\n || _validator == VALIDATOR_10\n || _validator == VALIDATOR_11\n || _validator == VALIDATOR_12\n || _validator == VALIDATOR_13\n || _validator == VALIDATOR_14\n );\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticSbx.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticSbx is StakingBankStatic {\n address public constant VALIDATOR_0 = 0xE3bDa0C6E1fBB111091Dfef6f22a673b20Ea5F50;\n address public constant VALIDATOR_1 = 0xc1773490F00963CBAb3841fc07C1a0796E658Ba2;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.sbx.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.sbx.umb.network\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0 || _validator == VALIDATOR_1);\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": false, + "runs": 0 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/avalanche_production/ForeignChain.json b/deployments/avalanche_production/ForeignChain.json index 4700c132..520cc018 100644 --- a/deployments/avalanche_production/ForeignChain.json +++ b/deployments/avalanche_production/ForeignChain.json @@ -1,5 +1,5 @@ { - "address": "0xF61d7DffdFA22091eAdb77E4Bc0Fb2f9B48384ca", + "address": "0xa01635f74380b31E3b2f1D55594e6199705B2a6B", "abi": [ { "inputs": [ @@ -1051,47 +1051,47 @@ "type": "function" } ], - "transactionHash": "0xcf1054609fa903508fc63e8106326e066cee3f5d17cf615b43e00009fe45f54e", + "transactionHash": "0xf5f48047c581c88ea59962c5dc51238ba5358b1450cb88ca12c44330fed95522", "receipt": { "to": null, "from": "0xA6e4fFa19B213AbeA258ae72e8e1a209B9E543e7", - "contractAddress": "0xF61d7DffdFA22091eAdb77E4Bc0Fb2f9B48384ca", - "transactionIndex": 9, - "gasUsed": "4444005", - "logsBloom": "0x00000000000000000000000000000000000000000000000000800000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000020400000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000010000000020000400000000000000000000000000000000000020000000000400000000000020000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x4083aff3462cf083c216d0e48a32352a68b5638b93e6550519bb0b21888dcf63", - "transactionHash": "0xcf1054609fa903508fc63e8106326e066cee3f5d17cf615b43e00009fe45f54e", + "contractAddress": "0xa01635f74380b31E3b2f1D55594e6199705B2a6B", + "transactionIndex": 3, + "gasUsed": "4445421", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000060400000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000010000000000000400000000000000000000000000000000000020000000000000000008000020000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x693fafcb52664f6d9ce98c877561e08adee0a317c36078b273212c6e420ef60c", + "transactionHash": "0xf5f48047c581c88ea59962c5dc51238ba5358b1450cb88ca12c44330fed95522", "logs": [ { - "transactionIndex": 9, - "blockNumber": 37449494, - "transactionHash": "0xcf1054609fa903508fc63e8106326e066cee3f5d17cf615b43e00009fe45f54e", - "address": "0xF61d7DffdFA22091eAdb77E4Bc0Fb2f9B48384ca", + "transactionIndex": 3, + "blockNumber": 52434811, + "transactionHash": "0xf5f48047c581c88ea59962c5dc51238ba5358b1450cb88ca12c44330fed95522", + "address": "0xa01635f74380b31E3b2f1D55594e6199705B2a6B", "topics": [ "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x000000000000000000000000a6e4ffa19b213abea258ae72e8e1a209b9e543e7" ], "data": "0x", - "logIndex": 13, - "blockHash": "0x4083aff3462cf083c216d0e48a32352a68b5638b93e6550519bb0b21888dcf63" + "logIndex": 7, + "blockHash": "0x693fafcb52664f6d9ce98c877561e08adee0a317c36078b273212c6e420ef60c" }, { - "transactionIndex": 9, - "blockNumber": 37449494, - "transactionHash": "0xcf1054609fa903508fc63e8106326e066cee3f5d17cf615b43e00009fe45f54e", - "address": "0xF61d7DffdFA22091eAdb77E4Bc0Fb2f9B48384ca", + "transactionIndex": 3, + "blockNumber": 52434811, + "transactionHash": "0xf5f48047c581c88ea59962c5dc51238ba5358b1450cb88ca12c44330fed95522", + "address": "0xa01635f74380b31E3b2f1D55594e6199705B2a6B", "topics": [ "0x02ff77a0f68d11f7efb906f331b2dda82916de8ba9c37dda2a95817936a530ec", "0x000000000000000000000000a6e4ffa19b213abea258ae72e8e1a209b9e543e7" ], "data": "0x000000000000000000000000000000000000000000000000000000000000ffff", - "logIndex": 14, - "blockHash": "0x4083aff3462cf083c216d0e48a32352a68b5638b93e6550519bb0b21888dcf63" + "logIndex": 8, + "blockHash": "0x693fafcb52664f6d9ce98c877561e08adee0a317c36078b273212c6e420ef60c" } ], - "blockNumber": 37449494, - "cumulativeGasUsed": "5208922", + "blockNumber": 52434811, + "cumulativeGasUsed": "4830755", "status": 1, "byzantium": true }, @@ -1102,7 +1102,7 @@ false ], "numDeployments": 1, - "solcInputHash": "4db3e1d3dd51dbe508dc0a6a04352df6", + "solcInputHash": "dc68422c0ad35a4fe46d461b096b9383", "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"_contractRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"_padding\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"_requiredSignatures\",\"type\":\"uint16\"},{\"internalType\":\"bool\",\"name\":\"_allowForMixedType\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyDeprecated\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArraysDataDoNotMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BlockSubmittedToFastOrDataToOld\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractNotReady\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FCDOverflow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContractType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoChangeToState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotEnoughSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotSupported\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyOwnerOrRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfOrder\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnregisterFirst\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"deprecator\",\"type\":\"address\"}],\"name\":\"LogDeprecation\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"blockId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"staked\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"power\",\"type\":\"uint256\"}],\"name\":\"LogMint\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"executor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"timePadding\",\"type\":\"uint32\"}],\"name\":\"LogPadding\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"blockId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"vote\",\"type\":\"uint256\"}],\"name\":\"LogVoter\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ETH_PREFIX\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_blockId\",\"type\":\"uint256\"}],\"name\":\"blocks\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"dataTimestamp\",\"type\":\"uint32\"}],\"internalType\":\"struct BaseChain.Block\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blocksCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blocksCountOffset\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_offset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_items\",\"type\":\"uint256\"}],\"name\":\"bytesToBytes32Array\",\"outputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"contractRegistry\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deprecate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"fcds\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"dataTimestamp\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockId\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"getBlockIdAtTimestamp\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_blockId\",\"type\":\"uint32\"}],\"name\":\"getBlockRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_blockId\",\"type\":\"uint32\"}],\"name\":\"getBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConsensusData\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"blocksCountOffset\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"sequence\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"lastTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"padding\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"deprecated\",\"type\":\"bool\"}],\"internalType\":\"struct BaseChain.ConsensusData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getCurrentIntValue\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"value\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getCurrentValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_keys\",\"type\":\"bytes32[]\"}],\"name\":\"getCurrentValues\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"uint32[]\",\"name\":\"timestamps\",\"type\":\"uint32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestBlockId\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLeaderAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"getLeaderAddressAtTime\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"getLeaderIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNextLeaderAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStatus\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"timePadding\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"lastDataTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"lastId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"nextLeader\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"nextBlockId\",\"type\":\"uint32\"},{\"internalType\":\"address[]\",\"name\":\"validators\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"powers\",\"type\":\"uint256[]\"},{\"internalType\":\"string[]\",\"name\":\"locations\",\"type\":\"string[]\"},{\"internalType\":\"uint256\",\"name\":\"staked\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"minSignatures\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_key\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_value\",\"type\":\"bytes\"}],\"name\":\"hashLeaf\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isForeign\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastBlockId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_affidavit\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"_v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"_r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_s\",\"type\":\"bytes32\"}],\"name\":\"recoverSigner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"register\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"requiredSignatures\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"roots\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"_padding\",\"type\":\"uint16\"}],\"name\":\"setPadding\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stakingBank\",\"outputs\":[{\"internalType\":\"contract IStakingBank\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stakingBankContract\",\"outputs\":[{\"internalType\":\"contract IStakingBank\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_dataTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"_root\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"_keys\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_values\",\"type\":\"uint256[]\"},{\"internalType\":\"uint8[]\",\"name\":\"_v\",\"type\":\"uint8[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"_r\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"_s\",\"type\":\"bytes32[]\"}],\"name\":\"submit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"tokenContract\",\"outputs\":[{\"internalType\":\"contract ERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_proof\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"_root\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_leaf\",\"type\":\"bytes32\"}],\"name\":\"verifyProof\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_blockId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"_proof\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"_key\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_value\",\"type\":\"bytes\"}],\"name\":\"verifyProofForBlock\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"_blockIds\",\"type\":\"uint32[]\"},{\"internalType\":\"bytes\",\"name\":\"_proofs\",\"type\":\"bytes\"},{\"internalType\":\"uint256[]\",\"name\":\"_proofItemsCounter\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"_leaves\",\"type\":\"bytes32[]\"}],\"name\":\"verifyProofs\",\"outputs\":[{\"internalType\":\"bool[]\",\"name\":\"results\",\"type\":\"bool[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"contract for foreign chains\",\"kind\":\"dev\",\"methods\":{\"blocks(uint256)\":{\"params\":{\"_blockId\":\"ID of submitted block\"},\"returns\":{\"_0\":\"block data (root + timestamp)\"}},\"blocksCount()\":{\"details\":\"number of blocks (consensus rounds) saved in this contract\"},\"bytesToBytes32Array(bytes,uint256,uint256)\":{\"details\":\"this is helper method, that extracts one merkle proof from many hashed provided as bytes\",\"params\":{\"_data\":\"many hashes as bytes\",\"_items\":\"how many hashes to extract\",\"_offset\":\"this is starting point for extraction\"},\"returns\":{\"_0\":\"merkle proof (array of bytes32 hashes)\"}},\"constructor\":{\"params\":{\"_contractRegistry\":\"Registry address\",\"_padding\":\"required \\\"space\\\" between blocks in seconds\",\"_requiredSignatures\":\"number of required signatures for accepting consensus submission\"}},\"getBlockId()\":{\"returns\":{\"_0\":\"current block ID please note, that current ID is not the same as last ID, current means that once padding pass, ID will switch to next one and it will be pointing to empty submit until submit for that ID is done\"}},\"getBlockIdAtTimestamp(uint256)\":{\"details\":\"calculates block ID for provided timestamp this function does not works for past timestamps\",\"params\":{\"_timestamp\":\"current or future timestamp\"},\"returns\":{\"_0\":\"block ID for provided timestamp\"}},\"getBlockRoot(uint32)\":{\"params\":{\"_blockId\":\"consensus ID\"},\"returns\":{\"_0\":\"root for provided consensus ID\"}},\"getBlockTimestamp(uint32)\":{\"params\":{\"_blockId\":\"consensus ID\"},\"returns\":{\"_0\":\"timestamp for provided consensus ID\"}},\"getConsensusData()\":{\"details\":\"getter for `_consensusData`\"},\"getCurrentIntValue(bytes32)\":{\"details\":\"getter for single FCD value in case its type is `int`\",\"params\":{\"_key\":\"FCD key\"},\"returns\":{\"timestamp\":\"FCD timestamp\",\"value\":\"FCD value\"}},\"getCurrentValue(bytes32)\":{\"details\":\"getter for single FCD value\",\"params\":{\"_key\":\"FCD key\"},\"returns\":{\"timestamp\":\"FCD timestamp\",\"value\":\"FCD value\"}},\"getCurrentValues(bytes32[])\":{\"details\":\"batch getter for FCDs\",\"params\":{\"_keys\":\"FCDs keys to fetch\"},\"returns\":{\"timestamps\":\"array of FCDs timestamps\",\"values\":\"array of FCDs values\"}},\"getLatestBlockId()\":{\"returns\":{\"_0\":\"last submitted block ID, please note, that on deployment, when there is no submission for this contract block for last ID will be available in previous contract\"}},\"getLeaderAddress()\":{\"returns\":{\"_0\":\"address of current leader\"}},\"getName()\":{\"returns\":{\"_0\":\"contract name as bytes32\"}},\"getNextLeaderAddress()\":{\"returns\":{\"_0\":\"address of leader for next second\"}},\"getStatus()\":{\"details\":\"helper method that returns all important data about current state of contract\",\"returns\":{\"blockNumber\":\"`block.number`\",\"lastDataTimestamp\":\"timestamp for last submitted consensus\",\"lastId\":\"ID of last submitted consensus\",\"locations\":\"array will be always empty\",\"minSignatures\":\"`this.requiredSignatures`\",\"nextBlockId\":\"block ID for `block.timestamp + padding`\",\"nextLeader\":\"will be always address(0)\",\"powers\":\"array will be always empty\",\"staked\":\"total UMB staked by validators\",\"timePadding\":\"`this.padding`\",\"validators\":\"array will be always empty\"}},\"hashLeaf(bytes,bytes)\":{\"details\":\"creates leaf hash, that has is used in merkle tree\",\"params\":{\"_key\":\"key under which we store the value\",\"_value\":\"value itself as bytes\"},\"returns\":{\"_0\":\"leaf hash\"}},\"isForeign()\":{\"returns\":{\"_0\":\"TRUE if contract is ForeignChain, FALSE otherwise\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"recoverSigner(bytes32,uint8,bytes32,bytes32)\":{\"params\":{\"_affidavit\":\"root and FCDs hashed together\",\"_r\":\"part of signature\",\"_s\":\"part of signature\",\"_v\":\"part of signature\"},\"returns\":{\"_0\":\"signer address\"}},\"register()\":{\"details\":\"this method will be called as a first method in registration process when old contract will be replaced when called, old contract address is still in registry\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setPadding(uint16)\":{\"details\":\"setter for `padding`\"},\"stakingBankContract()\":{\"details\":\"helper method for fetching StakingBank address\"},\"submit(uint32,bytes32,bytes32[],uint256[],uint8[],bytes32[],bytes32[])\":{\"details\":\"method for submitting consensus data\",\"params\":{\"_dataTimestamp\":\"consensus timestamp, this is time for all data in merkle tree including FCDs\",\"_keys\":\"FCDs keys\",\"_r\":\"array of `r` part of validators signatures\",\"_root\":\"merkle root\",\"_s\":\"array of `s` part of validators signatures\",\"_v\":\"array of `v` part of validators signatures\",\"_values\":\"FCDs values\"}},\"tokenContract()\":{\"details\":\"helper method for fetching UMB address\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"unregister()\":{\"details\":\"this method will be called as a last method in registration process when old contract will be replaced when called, new contract address is already in registry\"},\"verifyProof(bytes32[],bytes32,bytes32)\":{\"details\":\"verifies if the leaf is valid leaf for merkle tree\",\"params\":{\"_leaf\":\"leaf hash\",\"_proof\":\"merkle proof for merkle tree\",\"_root\":\"merkle root\"},\"returns\":{\"_0\":\"TRUE if `_leaf` is valid, FALSE otherwise\"}},\"verifyProofForBlock(uint256,bytes32[],bytes,bytes)\":{\"details\":\"verifies, if provided key-value pair was part of consensus\",\"params\":{\"_blockId\":\"consensus ID for which we doing a check\",\"_key\":\"pair key\",\"_proof\":\"merkle proof for pair\",\"_value\":\"pair value\"},\"returns\":{\"_0\":\"TRUE if key-value par was part of consensus, FALSE otherwise\"}},\"verifyProofs(uint32[],bytes,uint256[],bytes32[])\":{\"details\":\"batch method for data verification\",\"params\":{\"_blockIds\":\"consensus IDs for which we doing a checks\",\"_leaves\":\"array of merkle leaves\",\"_proofItemsCounter\":\"array of counters, each counter tells how many hashes proof for each leaf has\",\"_proofs\":\"merkle proofs for all pair, sequence of hashes provided as bytes\"},\"returns\":{\"results\":\"array of verification results, TRUE if leaf is part of consensus, FALSE otherwise\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"deprecate()\":{\"notice\":\"it allows to deprecate contract manually Only new Registry calls `unregister()` where we set deprecated to true In old Registries we don't have this feature, so in order to safely redeploy new Chain we will have to first deprecate current contract manually, then register new contract\"},\"getStatus()\":{\"notice\":\"this method is made to be compatible with MasterChain, but it does not return full data eg validators data will be missing.\"},\"register()\":{\"notice\":\"if this method needs to be called manually (not from Registry) it is important to do it as part of tx batch eg using multisig, we should prepare set of transactions and confirm them all at once\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/ForeignChain.sol\":\"ForeignChain\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":0},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0x24e0364e503a9bbde94c715d26573a76f14cd2a202d45f96f52134ab806b67b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\\n * instead returning `false` on failure. This behavior is nonetheless\\n * conventional and does not conflict with the expectations of ERC20\\n * applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * The default value of {decimals} is 18. To select a different value for\\n * {decimals} you should overload it.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n * overridden;\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\\n * `transferFrom`. This is semantically equivalent to an infinite approval.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * NOTE: Does not update the allowance if the current allowance\\n * is the maximum `uint256`.\\n *\\n * Requirements:\\n *\\n * - `from` and `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) public virtual override returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, amount);\\n _transfer(from, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, allowance(owner, spender) + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n uint256 currentAllowance = allowance(owner, spender);\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n */\\n function _transfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {\\n require(from != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(to != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, amount);\\n\\n uint256 fromBalance = _balances[from];\\n require(fromBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[from] = fromBalance - amount;\\n }\\n _balances[to] += amount;\\n\\n emit Transfer(from, to, amount);\\n\\n _afterTokenTransfer(from, to, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n _balances[account] += amount;\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n }\\n _totalSupply -= amount;\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(\\n address owner,\\n address spender,\\n uint256 amount\\n ) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\\n *\\n * Does not update the allowance amount in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Might emit an {Approval} event.\\n */\\n function _spendAllowance(\\n address owner,\\n address spender,\\n uint256 amount\\n ) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance != type(uint256).max) {\\n require(currentAllowance >= amount, \\\"ERC20: insufficient allowance\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - amount);\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {}\\n}\\n\",\"keccak256\":\"0xe0c8b625a79bac0fe80f17cfb521e072805cc9cef1c96a5caf45b264e74812fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/cryptography/MerkleProof.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev These functions deal with verification of Merkle Trees proofs.\\n *\\n * The proofs can be generated using the JavaScript library\\n * https://github.com/miguelmota/merkletreejs[merkletreejs].\\n * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.\\n *\\n * See `test/utils/cryptography/MerkleProof.test.js` for some examples.\\n *\\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\\n * hashing, or use a hash function other than keccak256 for hashing leaves.\\n * This is because the concatenation of a sorted pair of internal nodes in\\n * the merkle tree could be reinterpreted as a leaf value.\\n */\\nlibrary MerkleProof {\\n /**\\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\\n * defined by `root`. For this, a `proof` must be provided, containing\\n * sibling hashes on the branch from the leaf to the root of the tree. Each\\n * pair of leaves and each pair of pre-images are assumed to be sorted.\\n */\\n function verify(\\n bytes32[] memory proof,\\n bytes32 root,\\n bytes32 leaf\\n ) internal pure returns (bool) {\\n return processProof(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\\n * hash matches the root of the tree. When processing the proof, the pairs\\n * of leafs & pre-images are assumed to be sorted.\\n *\\n * _Available since v4.4._\\n */\\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n bytes32 proofElement = proof[i];\\n if (computedHash <= proofElement) {\\n // Hash(current computed hash + current element of the proof)\\n computedHash = _efficientHash(computedHash, proofElement);\\n } else {\\n // Hash(current element of the proof + current computed hash)\\n computedHash = _efficientHash(proofElement, computedHash);\\n }\\n }\\n return computedHash;\\n }\\n\\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\\n assembly {\\n mstore(0x00, a)\\n mstore(0x20, b)\\n value := keccak256(0x00, 0x40)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaaa504ac17eb0298dcdf5733ce24021b4914f035b97f4400b92827341d3facb3\",\"license\":\"MIT\"},\"@umb-network/toolbox/dist/contracts/lib/ValueDecoder.sol\":{\"content\":\"//SPDX-License-Identifier: Unlicensed\\npragma solidity >=0.6.8;\\n\\nlibrary ValueDecoder {\\n function toUint(bytes memory _bytes) internal pure returns (uint256 value) {\\n assembly {\\n value := mload(add(_bytes, 32))\\n }\\n }\\n\\n function toUint(bytes32 _bytes) internal pure returns (uint256 value) {\\n assembly {\\n value := _bytes\\n }\\n }\\n\\n function toInt(uint224 u) internal pure returns (int256) {\\n int224 i;\\n uint224 max = type(uint224).max;\\n\\n if (u <= (max - 1) / 2) { // positive values\\n assembly {\\n i := add(u, 0)\\n }\\n\\n return i;\\n } else { // negative values\\n assembly {\\n i := sub(sub(u, max), 1)\\n }\\n }\\n\\n return i;\\n }\\n}\\n\\n\",\"keccak256\":\"0x4c27669880111dd724930e6e2cb0baefdb3a8b7b2d6ffc0ec5c5534bc678a852\",\"license\":\"Unlicensed\"},\"contracts/BaseChain.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\\\";\\nimport \\\"@umb-network/toolbox/dist/contracts/lib/ValueDecoder.sol\\\";\\n\\nimport \\\"./interfaces/IBaseChainV1.sol\\\";\\nimport \\\"./interfaces/IStakingBank.sol\\\";\\nimport \\\"./extensions/Registrable.sol\\\";\\nimport \\\"./Registry.sol\\\";\\n\\nabstract contract BaseChain is Registrable, Ownable {\\n using ValueDecoder for bytes;\\n using ValueDecoder for uint224;\\n using MerkleProof for bytes32[];\\n\\n /// @param root merkle root for consensus\\n /// @param dataTimestamp consensus timestamp\\n struct Block {\\n bytes32 root;\\n uint32 dataTimestamp;\\n }\\n\\n /// @param value FCD value\\n /// @param dataTimestamp FCD timestamp\\n struct FirstClassData {\\n uint224 value;\\n uint32 dataTimestamp;\\n }\\n\\n /// @param blocksCountOffset number of all blocks that were generated before switching to this contract\\n /// @param sequence is a total number of blocks (consensus rounds) including previous contracts\\n /// @param lastTimestamp is a timestamp of last submitted block\\n /// @param padding number of seconds that need to pass before new submit will be possible\\n /// @param deprecated flag that changes to TRUE on `unregister`, when TRUE submissions are not longer available\\n struct ConsensusData {\\n uint32 blocksCountOffset;\\n uint32 sequence;\\n uint32 lastTimestamp;\\n uint32 padding;\\n bool deprecated;\\n }\\n\\n uint256 constant public VERSION = 2;\\n\\n bool internal immutable _ALLOW_FOR_MIXED_TYPE; // solhint-disable-line var-name-mixedcase\\n\\n bytes4 constant private _VERSION_SELECTOR = bytes4(keccak256(\\\"VERSION()\\\"));\\n\\n /// @dev minimal number of signatures required for accepting submission (PoA)\\n uint16 internal immutable _REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\\n\\n ConsensusData internal _consensusData;\\n\\n bytes constant public ETH_PREFIX = \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\";\\n\\n /// @dev block id (consensus ID) => root\\n /// consensus ID is at the same time consensus timestamp\\n mapping(uint256 => bytes32) public roots;\\n\\n /// @dev FCD key => FCD data\\n mapping(bytes32 => FirstClassData) public fcds;\\n\\n event LogDeprecation(address indexed deprecator);\\n event LogPadding(address indexed executor, uint32 timePadding);\\n\\n error ArraysDataDoNotMatch();\\n error AlreadyDeprecated();\\n error AlreadyRegistered();\\n error BlockSubmittedToFastOrDataToOld();\\n error ContractNotReady();\\n error FCDOverflow();\\n error InvalidContractType();\\n error NoChangeToState();\\n error OnlyOwnerOrRegistry();\\n error UnregisterFirst();\\n\\n modifier onlyOwnerOrRegistry () {\\n if (msg.sender != address(contractRegistry) && msg.sender != owner()) revert OnlyOwnerOrRegistry();\\n _;\\n }\\n\\n /// @param _contractRegistry Registry address\\n /// @param _padding required \\\"space\\\" between blocks in seconds\\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\\n constructor(\\n IRegistry _contractRegistry,\\n uint32 _padding,\\n uint16 _requiredSignatures,\\n bool _allowForMixedType\\n ) Registrable(_contractRegistry) {\\n _ALLOW_FOR_MIXED_TYPE = _allowForMixedType;\\n _REQUIRED_SIGNATURES = _requiredSignatures;\\n\\n _setPadding(_padding);\\n\\n BaseChain oldChain = BaseChain(_contractRegistry.getAddress(\\\"Chain\\\"));\\n\\n if (address(oldChain) == address(0)) {\\n // if this is first contract in sidechain, then we need to initialise lastTimestamp so submission\\n // can be possible\\n _consensusData.lastTimestamp = uint32(block.timestamp) - _padding - 1;\\n }\\n }\\n\\n /// @dev setter for `padding`\\n function setPadding(uint16 _padding) external {\\n _setPadding(_padding);\\n }\\n\\n /// @notice if this method needs to be called manually (not from Registry)\\n /// it is important to do it as part of tx batch\\n /// eg using multisig, we should prepare set of transactions and confirm them all at once\\n /// @inheritdoc Registrable\\n function register() external override onlyOwnerOrRegistry {\\n address oldChain = contractRegistry.getAddress(\\\"Chain\\\");\\n\\n // registration must be done before address in registry is replaced\\n if (oldChain == address(this)) revert AlreadyRegistered();\\n\\n if (oldChain == address(0x0)) {\\n return;\\n }\\n\\n _cloneLastDataFromPrevChain(oldChain);\\n }\\n\\n /// @inheritdoc Registrable\\n function unregister() external override onlyOwnerOrRegistry {\\n // in case we deprecated contract manually, we simply return\\n if (_consensusData.deprecated) return;\\n\\n address newChain = contractRegistry.getAddress(\\\"Chain\\\");\\n // unregistering must be done after address in registry is replaced\\n if (newChain == address(this)) revert UnregisterFirst();\\n\\n // TODO:\\n // I think we need to remove restriction for type (at least once)\\n // when we will switch to multichain architecture\\n\\n if (!_ALLOW_FOR_MIXED_TYPE) {\\n // can not be replaced with chain of different type\\n if (BaseChain(newChain).isForeign() != this.isForeign()) revert InvalidContractType();\\n }\\n\\n _consensusData.deprecated = true;\\n emit LogDeprecation(msg.sender);\\n }\\n\\n /// @notice it allows to deprecate contract manually\\n /// Only new Registry calls `unregister()` where we set deprecated to true\\n /// In old Registries we don't have this feature, so in order to safely redeploy new Chain\\n /// we will have to first deprecate current contract manually, then register new contract\\n function deprecate() external onlyOwnerOrRegistry {\\n if (_consensusData.deprecated) revert AlreadyDeprecated();\\n\\n _consensusData.deprecated = true;\\n emit LogDeprecation(msg.sender);\\n }\\n\\n /// @dev getter for `_consensusData`\\n function getConsensusData() external view returns (ConsensusData memory) {\\n return _consensusData;\\n }\\n\\n /// @dev number of blocks (consensus rounds) saved in this contract\\n function blocksCount() external view returns (uint256) {\\n return _consensusData.sequence - _consensusData.blocksCountOffset;\\n }\\n\\n function blocksCountOffset() external view returns (uint32) {\\n return _consensusData.blocksCountOffset;\\n }\\n\\n function lastBlockId() external view returns (uint256) {\\n return _consensusData.lastTimestamp;\\n }\\n\\n /// @return TRUE if contract is ForeignChain, FALSE otherwise\\n function isForeign() external pure virtual returns (bool);\\n\\n /// @inheritdoc Registrable\\n function getName() external pure override returns (bytes32) {\\n return \\\"Chain\\\";\\n }\\n\\n /// @param _affidavit root and FCDs hashed together\\n /// @param _v part of signature\\n /// @param _r part of signature\\n /// @param _s part of signature\\n /// @return signer address\\n function recoverSigner(bytes32 _affidavit, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _affidavit));\\n return ecrecover(hash, _v, _r, _s);\\n }\\n\\n /// @param _blockId ID of submitted block\\n /// @return block data (root + timestamp)\\n function blocks(uint256 _blockId) external view returns (Block memory) {\\n return Block(roots[_blockId], uint32(_blockId));\\n }\\n\\n /// @return current block ID\\n /// please note, that current ID is not the same as last ID, current means that once padding pass,\\n /// ID will switch to next one and it will be pointing to empty submit until submit for that ID is done\\n function getBlockId() external view returns (uint32) {\\n if (_consensusData.lastTimestamp == 0) return 0;\\n\\n return getBlockIdAtTimestamp(block.timestamp);\\n }\\n\\n function requiredSignatures() external view returns (uint16) {\\n return _REQUIRED_SIGNATURES;\\n }\\n\\n /// @dev calculates block ID for provided timestamp\\n /// this function does not works for past timestamps\\n /// @param _timestamp current or future timestamp\\n /// @return block ID for provided timestamp\\n function getBlockIdAtTimestamp(uint256 _timestamp) virtual public view returns (uint32) {\\n ConsensusData memory data = _consensusData;\\n\\n unchecked {\\n // we can't overflow because we adding two `uint32`\\n if (data.lastTimestamp + data.padding < _timestamp) {\\n return uint32(_timestamp);\\n }\\n }\\n\\n return data.lastTimestamp;\\n }\\n\\n /// @return last submitted block ID, please note, that on deployment, when there is no submission for this contract\\n /// block for last ID will be available in previous contract\\n function getLatestBlockId() virtual public view returns (uint32) {\\n return _consensusData.lastTimestamp;\\n }\\n\\n /// @dev verifies if the leaf is valid leaf for merkle tree\\n /// @param _proof merkle proof for merkle tree\\n /// @param _root merkle root\\n /// @param _leaf leaf hash\\n /// @return TRUE if `_leaf` is valid, FALSE otherwise\\n function verifyProof(bytes32[] memory _proof, bytes32 _root, bytes32 _leaf) public pure returns (bool) {\\n if (_root == bytes32(0)) {\\n return false;\\n }\\n\\n return _proof.verify(_root, _leaf);\\n }\\n\\n /// @dev creates leaf hash, that has is used in merkle tree\\n /// @param _key key under which we store the value\\n /// @param _value value itself as bytes\\n /// @return leaf hash\\n function hashLeaf(bytes memory _key, bytes memory _value) public pure returns (bytes32) {\\n return keccak256(abi.encodePacked(_key, _value));\\n }\\n\\n /// @dev verifies, if provided key-value pair was part of consensus\\n /// @param _blockId consensus ID for which we doing a check\\n /// @param _proof merkle proof for pair\\n /// @param _key pair key\\n /// @param _value pair value\\n /// @return TRUE if key-value par was part of consensus, FALSE otherwise\\n function verifyProofForBlock(\\n uint256 _blockId,\\n bytes32[] memory _proof,\\n bytes memory _key,\\n bytes memory _value\\n )\\n public\\n view\\n returns (bool)\\n {\\n return _proof.verify(roots[_blockId], keccak256(abi.encodePacked(_key, _value)));\\n }\\n\\n /// @dev this is helper method, that extracts one merkle proof from many hashed provided as bytes\\n /// @param _data many hashes as bytes\\n /// @param _offset this is starting point for extraction\\n /// @param _items how many hashes to extract\\n /// @return merkle proof (array of bytes32 hashes)\\n function bytesToBytes32Array(\\n bytes memory _data,\\n uint256 _offset,\\n uint256 _items\\n )\\n public\\n pure\\n returns (bytes32[] memory)\\n {\\n bytes32[] memory dataList = new bytes32[](_items);\\n\\n // we can unchecked because we working only with `i` and `_offset`\\n // in case of wrong `_offset` it will throw\\n unchecked {\\n for (uint256 i = 0; i < _items; i++) {\\n bytes32 temp;\\n uint256 idx = (i + 1 + _offset) * 32;\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n temp := mload(add(_data, idx))\\n }\\n\\n dataList[i] = temp;\\n }\\n }\\n\\n return (dataList);\\n }\\n\\n /// @dev batch method for data verification\\n /// @param _blockIds consensus IDs for which we doing a checks\\n /// @param _proofs merkle proofs for all pair, sequence of hashes provided as bytes\\n /// @param _proofItemsCounter array of counters, each counter tells how many hashes proof for each leaf has\\n /// @param _leaves array of merkle leaves\\n /// @return results array of verification results, TRUE if leaf is part of consensus, FALSE otherwise\\n function verifyProofs(\\n uint32[] memory _blockIds,\\n bytes memory _proofs,\\n uint256[] memory _proofItemsCounter,\\n bytes32[] memory _leaves\\n )\\n public\\n view\\n returns (bool[] memory results)\\n {\\n results = new bool[](_leaves.length);\\n uint256 offset = 0;\\n\\n for (uint256 i = 0; i < _leaves.length;) {\\n results[i] = bytesToBytes32Array(_proofs, offset, _proofItemsCounter[i]).verify(\\n roots[_blockIds[i]], _leaves[i]\\n );\\n\\n unchecked {\\n // we can uncheck because it will not overflow in a lifetime, and if someone provide invalid counter\\n // we verification will not be valid (or we throw because of invalid memory access)\\n offset += _proofItemsCounter[i];\\n // we can uncheck because `i` will not overflow in a lifetime\\n i++;\\n }\\n }\\n }\\n\\n /// @param _blockId consensus ID\\n /// @return root for provided consensus ID\\n function getBlockRoot(uint32 _blockId) external view returns (bytes32) {\\n return roots[_blockId];\\n }\\n\\n /// @param _blockId consensus ID\\n /// @return timestamp for provided consensus ID\\n function getBlockTimestamp(uint32 _blockId) external view returns (uint32) {\\n return roots[_blockId] == bytes32(0) ? 0 : _blockId;\\n }\\n\\n /// @dev batch getter for FCDs\\n /// @param _keys FCDs keys to fetch\\n /// @return values array of FCDs values\\n /// @return timestamps array of FCDs timestamps\\n function getCurrentValues(bytes32[] calldata _keys)\\n external\\n view\\n returns (uint256[] memory values, uint32[] memory timestamps)\\n {\\n timestamps = new uint32[](_keys.length);\\n values = new uint256[](_keys.length);\\n\\n for (uint i=0; i<_keys.length;) {\\n FirstClassData storage numericFCD = fcds[_keys[i]];\\n values[i] = uint256(numericFCD.value);\\n timestamps[i] = numericFCD.dataTimestamp;\\n\\n unchecked {\\n // we can uncheck because `i` will not overflow in a lifetime\\n i++;\\n }\\n }\\n }\\n\\n /// @dev getter for single FCD value\\n /// @param _key FCD key\\n /// @return value FCD value\\n /// @return timestamp FCD timestamp\\n function getCurrentValue(bytes32 _key) external view returns (uint256 value, uint256 timestamp) {\\n FirstClassData storage numericFCD = fcds[_key];\\n return (uint256(numericFCD.value), numericFCD.dataTimestamp);\\n }\\n\\n /// @dev getter for single FCD value in case its type is `int`\\n /// @param _key FCD key\\n /// @return value FCD value\\n /// @return timestamp FCD timestamp\\n function getCurrentIntValue(bytes32 _key) external view returns (int256 value, uint256 timestamp) {\\n FirstClassData storage numericFCD = fcds[_key];\\n return (numericFCD.value.toInt(), numericFCD.dataTimestamp);\\n }\\n\\n function _setPadding(uint32 _padding) internal onlyOwner {\\n if (_consensusData.padding == _padding) revert NoChangeToState();\\n\\n _consensusData.padding = _padding;\\n emit LogPadding(msg.sender, _padding);\\n }\\n\\n /// @dev we cloning last block time, because we will need reference point for next submissions\\n function _cloneLastDataFromPrevChain(address _prevChain) internal {\\n (bool success, bytes memory v) = _prevChain.staticcall(abi.encode(_VERSION_SELECTOR));\\n uint256 prevVersion = success ? abi.decode(v, (uint256)) : 1;\\n\\n if (prevVersion == 1) {\\n uint32 latestId = IBaseChainV1(address(_prevChain)).getLatestBlockId();\\n _consensusData.lastTimestamp = IBaseChainV1(address(_prevChain)).getBlockTimestamp(latestId);\\n\\n // +1 because getLatestBlockId subtracts 1\\n // +1 because it might be situation when tx is already in progress in old contract\\n // and old contract do not have deprecated flag\\n _consensusData.sequence = latestId + 2;\\n _consensusData.blocksCountOffset = latestId + 2;\\n } else { // VERSION 2\\n // with new Registry, we have register/unregister methods\\n // Chain will be deprecated, so there is no need to do \\\"+1\\\" as in old version\\n // TODO what with current Registries??\\n // we need a way to make it deprecated!\\n ConsensusData memory data = BaseChain(_prevChain).getConsensusData();\\n\\n _consensusData.sequence = data.sequence;\\n _consensusData.blocksCountOffset = data.sequence;\\n _consensusData.lastTimestamp = data.lastTimestamp;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcc7d655ad64f0a17cd71331260cf48828f0396e5e3b1428b6690c12f35a95db7\",\"license\":\"MIT\"},\"contracts/Chain.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./BaseChain.sol\\\";\\n\\ncontract Chain is BaseChain {\\n IStakingBank public immutable stakingBank;\\n\\n event LogMint(address indexed minter, uint256 blockId, uint256 staked, uint256 power);\\n event LogVoter(uint256 indexed blockId, address indexed voter, uint256 vote);\\n\\n error NotEnoughSignatures();\\n error SignaturesOutOfOrder();\\n\\n /// @param _contractRegistry Registry address\\n /// @param _padding required \\\"space\\\" between blocks in seconds\\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\\n /// @param _allowForMixedType we have two \\\"types\\\" of Chain: HomeChain and ForeignChain, when we redeploying\\n /// we don't want to mix up them, so we checking, if new Chain has the same type as current one.\\n /// However, when we will be switching from one homechain to another one, we have to allow for this mixing up.\\n /// This flag will tell contract, if this is the case.\\n constructor(\\n IRegistry _contractRegistry,\\n uint32 _padding,\\n uint16 _requiredSignatures,\\n bool _allowForMixedType\\n ) BaseChain(_contractRegistry, _padding, _requiredSignatures, _allowForMixedType) {\\n stakingBank = IStakingBank(_contractRegistry.requireAndGetAddress(\\\"StakingBank\\\"));\\n }\\n\\n /// @dev method for submitting consensus data\\n /// @param _dataTimestamp consensus timestamp, this is time for all data in merkle tree including FCDs\\n /// @param _root merkle root\\n /// @param _keys FCDs keys\\n /// @param _values FCDs values\\n /// @param _v array of `v` part of validators signatures\\n /// @param _r array of `r` part of validators signatures\\n /// @param _s array of `s` part of validators signatures\\n // solhint-disable-next-line function-max-lines, code-complexity\\n function submit(\\n uint32 _dataTimestamp,\\n bytes32 _root,\\n bytes32[] memory _keys,\\n uint256[] memory _values,\\n uint8[] memory _v,\\n bytes32[] memory _r,\\n bytes32[] memory _s\\n ) external {\\n // below two checks are only for pretty errors, so we can safe gas and allow for raw revert\\n // if (_keys.length != _values.length) revert ArraysDataDoNotMatch();\\n // if (_v.length != _r.length || _r.length != _s.length) revert ArraysDataDoNotMatch();\\n\\n _verifySubmitTimestampAndIncSequence(_dataTimestamp);\\n\\n // we can't expect minter will have exactly the same timestamp\\n // but for sure we can demand not to be off by a lot, that's why +3sec\\n // temporary remove this condition, because recently on ropsten we see cases when minter/node\\n // can be even 100sec behind\\n // require(_dataTimestamp <= block.timestamp + 3,\\n // string(abi.encodePacked(\\\"oh, so you can predict the future:\\\", _dataTimestamp - block.timestamp + 48)));\\n\\n bytes memory testimony = abi.encodePacked(_dataTimestamp, _root);\\n\\n for (uint256 i = 0; i < _keys.length;) {\\n if (uint224(_values[i]) != _values[i]) revert FCDOverflow();\\n\\n fcds[_keys[i]] = FirstClassData(uint224(_values[i]), _dataTimestamp);\\n testimony = abi.encodePacked(testimony, _keys[i], _values[i]);\\n\\n unchecked {\\n // we can't pass enough data to overflow\\n i++;\\n }\\n }\\n\\n uint256 signatures = 0;\\n uint256 power = 0;\\n //uint256 staked = stakingBank.totalSupply();\\n bytes32 affidavit = keccak256(testimony);\\n\\n address prevSigner = address(0x0);\\n\\n for (uint256 i; i < _v.length;) {\\n address signer = recoverSigner(affidavit, _v[i], _r[i], _s[i]);\\n uint256 balance = stakingBank.balanceOf(signer);\\n\\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\\n\\n prevSigner = signer;\\n\\n if (balance == 0) {\\n unchecked { i++; }\\n continue;\\n }\\n\\n signatures++;\\n emit LogVoter(uint256(_dataTimestamp), signer, balance);\\n\\n unchecked {\\n // we can't overflow because that means token overflowed\\n // and even if we do, we will get lower power\\n power += balance;\\n i++;\\n }\\n }\\n\\n if (signatures < _REQUIRED_SIGNATURES) revert NotEnoughSignatures();\\n\\n emit LogMint(msg.sender, _dataTimestamp, stakingBank.totalSupply(), power);\\n\\n // TODO remember to protect against flash loans when DPoS will be in place\\n // we turn on power once we have DPoS in action, we have PoA now\\n // require(power * 100 / staked >= 66, \\\"not enough power was gathered\\\");\\n\\n roots[_dataTimestamp] = _root;\\n _consensusData.lastTimestamp = _dataTimestamp;\\n }\\n\\n /// @inheritdoc BaseChain\\n function isForeign() external pure virtual override returns (bool) {\\n return false;\\n }\\n\\n /// @dev helper method that returns all important data about current state of contract\\n /// @return blockNumber `block.number`\\n /// @return timePadding `this.padding`\\n /// @return lastDataTimestamp timestamp for last submitted consensus\\n /// @return lastId ID of last submitted consensus\\n /// @return nextLeader leader for `block.timestamp + 1`\\n /// @return nextBlockId block ID for `block.timestamp + padding`\\n /// @return validators array of all validators addresses\\n /// @return powers array of all validators powers\\n /// @return locations array of all validators locations\\n /// @return staked total UMB staked by validators\\n /// @return minSignatures `this.requiredSignatures`\\n function getStatus() external view virtual returns(\\n uint256 blockNumber,\\n uint32 timePadding,\\n uint32 lastDataTimestamp,\\n uint32 lastId,\\n address nextLeader,\\n uint32 nextBlockId,\\n address[] memory validators,\\n uint256[] memory powers,\\n string[] memory locations,\\n uint256 staked,\\n uint16 minSignatures\\n ) {\\n ConsensusData memory data = _consensusData;\\n\\n blockNumber = block.number;\\n timePadding = data.padding;\\n lastId = data.lastTimestamp;\\n lastDataTimestamp = lastId;\\n minSignatures = _REQUIRED_SIGNATURES;\\n\\n staked = stakingBank.totalSupply();\\n uint256 numberOfValidators = stakingBank.getNumberOfValidators();\\n powers = new uint256[](numberOfValidators);\\n validators = new address[](numberOfValidators);\\n locations = new string[](numberOfValidators);\\n\\n for (uint256 i = 0; i < numberOfValidators;) {\\n validators[i] = stakingBank.addresses(i);\\n (, locations[i]) = stakingBank.validators(validators[i]);\\n powers[i] = stakingBank.balanceOf(validators[i]);\\n\\n unchecked {\\n // we will run out of gas before overflow happen\\n i++;\\n }\\n }\\n\\n unchecked {\\n // we will not overflow with timestamp in a lifetime\\n nextBlockId = lastId + data.padding + 1;\\n\\n nextLeader = numberOfValidators > 0\\n // we will not overflow with timestamp in a lifetime\\n ? validators[getLeaderIndex(numberOfValidators, block.timestamp + 1)]\\n : address(0);\\n }\\n }\\n\\n /// @return address of leader for next second\\n function getNextLeaderAddress() external view returns (address) {\\n return getLeaderAddressAtTime(block.timestamp + 1);\\n }\\n\\n /// @return address of current leader\\n function getLeaderAddress() external view returns (address) {\\n return getLeaderAddressAtTime(block.timestamp);\\n }\\n\\n /// @param _numberOfValidators total number of validators\\n /// @param _timestamp timestamp for which you want to calculate index\\n /// @return leader index, use it for StakingBank.addresses[index] to fetch leader address\\n function getLeaderIndex(uint256 _numberOfValidators, uint256 _timestamp) public view virtual returns (uint256) {\\n ConsensusData memory data = _consensusData;\\n\\n unchecked {\\n // we will not overflow on `timestamp` and `padding` in a life time\\n // timePadding + 1 => because padding is a space between blocks,\\n // so next round starts on first block after padding\\n // TODO will it work for off-chain??\\n uint256 validatorIndex = data.sequence + (_timestamp - data.lastTimestamp) / (data.padding + 1);\\n\\n return validatorIndex % _numberOfValidators;\\n }\\n }\\n\\n // @todo - properly handled non-enabled validators, newly added validators, and validators with low stake\\n /// @param _timestamp timestamp for which you want to calculate leader address\\n /// @return leader address for provider timestamp\\n function getLeaderAddressAtTime(uint256 _timestamp) public view virtual returns (address) {\\n uint256 numberOfValidators = stakingBank.getNumberOfValidators();\\n\\n if (numberOfValidators == 0) {\\n return address(0x0);\\n }\\n\\n uint256 validatorIndex = getLeaderIndex(numberOfValidators, _timestamp);\\n\\n return stakingBank.addresses(validatorIndex);\\n }\\n\\n /// @dev we had stack too deep in `submit` so this method was created as a solution\\n // we increasing `_consensusData.sequence` here so we don't have to read sequence again in other place\\n function _verifySubmitTimestampAndIncSequence(uint256 _dataTimestamp) internal {\\n ConsensusData memory data = _consensusData;\\n\\n // `data.lastTimestamp` must be setup either on deployment\\n // or via cloning from previous contract\\n if (data.lastTimestamp == 0) revert ContractNotReady();\\n\\n unchecked {\\n // we will not overflow with timestamp and padding in a life time\\n if (data.lastTimestamp + data.padding >= _dataTimestamp) revert BlockSubmittedToFastOrDataToOld();\\n }\\n\\n unchecked {\\n // we will not overflow in a life time\\n _consensusData.sequence = uint32(data.sequence + 1);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9eb872eaabac21d63c759e91507992710232a362afad6aa3221a8758d66f4e69\",\"license\":\"MIT\"},\"contracts/ForeignChain.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./Chain.sol\\\";\\n\\n/// @dev contract for foreign chains\\ncontract ForeignChain is Chain {\\n error NotSupported();\\n\\n /// @param _contractRegistry Registry address\\n /// @param _padding required \\\"space\\\" between blocks in seconds\\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\\n constructor(\\n IRegistry _contractRegistry,\\n uint32 _padding,\\n uint16 _requiredSignatures,\\n bool _allowForMixedType\\n ) Chain(_contractRegistry, _padding, _requiredSignatures, _allowForMixedType) {\\n // no additional configuration needed\\n }\\n\\n /// @inheritdoc BaseChain\\n function isForeign() external pure override returns (bool) {\\n return true;\\n }\\n\\n /// @inheritdoc Chain\\n /// @notice this method is made to be compatible with MasterChain, but it does not return full data eg validators\\n /// data will be missing.\\n /// @return blockNumber `block.number`\\n /// @return timePadding `this.padding`\\n /// @return lastDataTimestamp timestamp for last submitted consensus\\n /// @return lastId ID of last submitted consensus\\n /// @return nextLeader will be always address(0)\\n /// @return nextBlockId block ID for `block.timestamp + padding`\\n /// @return validators array will be always empty\\n /// @return powers array will be always empty\\n /// @return locations array will be always empty\\n /// @return staked total UMB staked by validators\\n /// @return minSignatures `this.requiredSignatures`\\n function getStatus() external view override returns(\\n uint256 blockNumber,\\n uint32 timePadding,\\n uint32 lastDataTimestamp,\\n uint32 lastId,\\n address nextLeader,\\n uint32 nextBlockId,\\n address[] memory validators,\\n uint256[] memory powers,\\n string[] memory locations,\\n uint256 staked,\\n uint16 minSignatures\\n ) {\\n ConsensusData memory data = _consensusData;\\n\\n blockNumber = block.number;\\n timePadding = data.padding;\\n lastId = data.lastTimestamp;\\n lastDataTimestamp = lastId;\\n minSignatures = _REQUIRED_SIGNATURES;\\n\\n staked = stakingBank.totalSupply();\\n uint256 numberOfValidators = 0;\\n powers = new uint256[](numberOfValidators);\\n validators = new address[](numberOfValidators);\\n locations = new string[](numberOfValidators);\\n nextLeader = address(0);\\n\\n unchecked {\\n // we will not overflow with timestamp in a lifetime\\n nextBlockId = lastId + data.padding + 1;\\n }\\n }\\n\\n function getLeaderIndex(uint256, uint256) public pure override returns (uint256) {\\n revert NotSupported();\\n }\\n\\n function getLeaderAddressAtTime(uint256) public pure override returns (address) {\\n revert NotSupported();\\n }\\n}\\n\",\"keccak256\":\"0x5b895277453aa3741c2659f335c2a4d587ff231615e4ee160bd2ec8e78778d49\",\"license\":\"MIT\"},\"contracts/Registry.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\n// Inheritance\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport \\\"./extensions/Registrable.sol\\\";\\nimport \\\"./interfaces/IRegistry.sol\\\";\\n\\n/// @dev contracts registry\\n/// protocol uses this registry to fetch current contract addresses\\ncontract Registry is IRegistry, Ownable {\\n /// name => contract address\\n mapping(bytes32 => address) public registry;\\n\\n\\n error NameNotRegistered();\\n error ArraysDataDoNotMatch();\\n\\n /// @inheritdoc IRegistry\\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external onlyOwner {\\n if (_names.length != _destinations.length) revert ArraysDataDoNotMatch();\\n\\n for (uint i = 0; i < _names.length;) {\\n registry[_names[i]] = _destinations[i];\\n emit LogRegistered(_destinations[i], _names[i]);\\n\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @inheritdoc IRegistry\\n function importContracts(address[] calldata _destinations) external onlyOwner {\\n for (uint i = 0; i < _destinations.length;) {\\n bytes32 name = Registrable(_destinations[i]).getName();\\n registry[name] = _destinations[i];\\n emit LogRegistered(_destinations[i], name);\\n\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @inheritdoc IRegistry\\n function atomicUpdate(address _newContract) external onlyOwner {\\n Registrable(_newContract).register();\\n\\n bytes32 name = Registrable(_newContract).getName();\\n address oldContract = registry[name];\\n registry[name] = _newContract;\\n\\n Registrable(oldContract).unregister();\\n\\n emit LogRegistered(_newContract, name);\\n }\\n\\n /// @inheritdoc IRegistry\\n function requireAndGetAddress(bytes32 name) external view returns (address) {\\n address _foundAddress = registry[name];\\n if (_foundAddress == address(0)) revert NameNotRegistered();\\n\\n return _foundAddress;\\n }\\n\\n /// @inheritdoc IRegistry\\n function getAddress(bytes32 _bytes) external view returns (address) {\\n return registry[_bytes];\\n }\\n\\n /// @inheritdoc IRegistry\\n function getAddressByString(string memory _name) public view returns (address) {\\n return registry[stringToBytes32(_name)];\\n }\\n\\n /// @inheritdoc IRegistry\\n function stringToBytes32(string memory _string) public pure returns (bytes32 result) {\\n bytes memory tempEmptyStringTest = bytes(_string);\\n\\n if (tempEmptyStringTest.length == 0) {\\n return 0x0;\\n }\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n result := mload(add(_string, 32))\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcf8ac18bf5766420afcc70f34339192fa67169106ccdb51573267a1ffd95fb81\",\"license\":\"MIT\"},\"contracts/extensions/Registrable.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"../interfaces/IRegistry.sol\\\";\\nimport \\\"../interfaces/IStakingBank.sol\\\";\\n\\n/// @dev Any contract that we want to register in ContractRegistry, must inherit from Registrable\\nabstract contract Registrable {\\n IRegistry public immutable contractRegistry;\\n\\n modifier onlyFromContract(address _msgSender, bytes32 _contractName) {\\n require(\\n contractRegistry.getAddress(_contractName) == _msgSender,\\n string(abi.encodePacked(\\\"caller is not \\\", _contractName))\\n );\\n _;\\n }\\n\\n modifier withRegistrySetUp() {\\n require(address(contractRegistry) != address(0x0), \\\"_registry is empty\\\");\\n _;\\n }\\n\\n constructor(IRegistry _contractRegistry) {\\n require(address(_contractRegistry) != address(0x0), \\\"_registry is empty\\\");\\n contractRegistry = _contractRegistry;\\n }\\n\\n /// @dev this method will be called as a first method in registration process when old contract will be replaced\\n /// when called, old contract address is still in registry\\n function register() virtual external;\\n\\n /// @dev this method will be called as a last method in registration process when old contract will be replaced\\n /// when called, new contract address is already in registry\\n function unregister() virtual external;\\n\\n /// @return contract name as bytes32\\n function getName() virtual external pure returns (bytes32);\\n\\n /// @dev helper method for fetching StakingBank address\\n function stakingBankContract() public view returns (IStakingBank) {\\n return IStakingBank(contractRegistry.requireAndGetAddress(\\\"StakingBank\\\"));\\n }\\n\\n /// @dev helper method for fetching UMB address\\n function tokenContract() public view withRegistrySetUp returns (ERC20) {\\n return ERC20(contractRegistry.requireAndGetAddress(\\\"UMB\\\"));\\n }\\n}\\n\",\"keccak256\":\"0x58413fc819ff8f78ba80a9339bf6b4bb818932ddef0ce58dd4813acba01bda8c\",\"license\":\"MIT\"},\"contracts/interfaces/IBaseChainV1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IBaseChainV1 {\\n /// @dev number of blocks (consensus rounds) saved in this contract\\n function blocksCount() external returns (uint32);\\n\\n /// @dev number of all blocks that were generated before switching to this contract\\n /// please note, that there might be a gap of one block when we switching from old to new contract\\n /// see constructor for details\\n function blocksCountOffset() external returns (uint32);\\n\\n function getLatestBlockId() external view returns (uint32);\\n\\n function getBlockTimestamp(uint32 _blockId) external view returns (uint32);\\n\\n function getStatus() external view returns (\\n uint256 blockNumber,\\n uint16 timePadding,\\n uint32 lastDataTimestamp,\\n uint32 lastId,\\n uint32 nextBlockId\\n );\\n}\\n\",\"keccak256\":\"0x4196faa25b921cae447328983f172ee4289591b4136fdde54ad05552c559d371\",\"license\":\"MIT\"},\"contracts/interfaces/IRegistry.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\n\\ninterface IRegistry {\\n event LogRegistered(address indexed destination, bytes32 name);\\n\\n /// @dev imports new contract addresses and override old addresses, if they exist under provided name\\n /// This method can be used for contracts that for some reason do not have `getName` method\\n /// @param _names array of contract names that we want to register\\n /// @param _destinations array of contract addresses\\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external;\\n\\n /// @dev imports new contracts and override old addresses, if they exist.\\n /// Names of contracts are fetched directly from each contract by calling `getName`\\n /// @param _destinations array of contract addresses\\n function importContracts(address[] calldata _destinations) external;\\n\\n /// @dev this method ensure, that old and new contract is aware of it state in registry\\n /// Note: BSC registry does not have this method. This method was introduced in later stage.\\n /// @param _newContract address of contract that will replace old one\\n function atomicUpdate(address _newContract) external;\\n\\n /// @dev similar to `getAddress` but throws when contract name not exists\\n /// @param name contract name\\n /// @return contract address registered under provided name or throws, if does not exists\\n function requireAndGetAddress(bytes32 name) external view returns (address);\\n\\n /// @param name contract name in a form of bytes32\\n /// @return contract address registered under provided name\\n function getAddress(bytes32 name) external view returns (address);\\n\\n /// @param _name contract name\\n /// @return contract address assigned to the name or address(0) if not exists\\n function getAddressByString(string memory _name) external view returns (address);\\n\\n /// @dev helper method that converts string to bytes32,\\n /// you can use to to generate contract name\\n function stringToBytes32(string memory _string) external pure returns (bytes32 result);\\n}\\n\",\"keccak256\":\"0xa0099ecf4182138fda7a0733407784461410c245de67c1e7ba7cd7c9595e054f\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBank.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IStakingBank is IERC20 {\\n /// @param id address of validator wallet\\n /// @param location URL of the validator API\\n struct Validator {\\n address id;\\n string location;\\n }\\n\\n event LogValidatorRegistered(address indexed id);\\n event LogValidatorUpdated(address indexed id);\\n event LogValidatorRemoved(address indexed id);\\n event LogMinAmountForStake(uint256 minAmountForStake);\\n\\n /// @dev setter for `minAmountForStake`\\n function setMinAmountForStake(uint256 _minAmountForStake) external;\\n\\n /// @dev allows to stake `token` by validators\\n /// Validator needs to approve StakingBank beforehand\\n /// @param _value amount of tokens to stake\\n function stake(uint256 _value) external;\\n\\n /// @dev notification about approval from `_from` address on UMB token\\n /// Staking bank will stake max approved amount from `_from` address\\n /// @param _from address which approved token spend for IStakingBank\\n function receiveApproval(address _from) external returns (bool success);\\n\\n /// @dev withdraws stake tokens\\n /// it throws, when balance will be less than required minimum for stake\\n /// to withdraw all use `exit`\\n function withdraw(uint256 _value) external returns (bool success);\\n\\n /// @dev unstake and withdraw all tokens\\n function exit() external returns (bool success);\\n\\n /// @dev creates (register) new validator\\n /// @param _id validator address\\n /// @param _location location URL of the validator API\\n function create(address _id, string calldata _location) external;\\n\\n /// @dev removes validator\\n /// @param _id validator wallet\\n function remove(address _id) external;\\n\\n /// @dev updates validator location\\n /// @param _id validator wallet\\n /// @param _location new validator URL\\n function update(address _id, string calldata _location) external;\\n\\n /// @return total number of registered validators (with and without balance)\\n function getNumberOfValidators() external view returns (uint256);\\n\\n /// @dev gets validator address for provided index\\n /// @param _ix index in array of list of all validators wallets\\n function addresses(uint256 _ix) external view returns (address);\\n\\n /// @param _id address of validator\\n /// @return id address of validator\\n /// @return location URL of validator\\n function validators(address _id) external view returns (address id, string memory location);\\n}\\n\",\"keccak256\":\"0x2c518aeab8b0b3a364fafaec559d3ff0dc6a119f8d203fa31ef7ad667ca0f7b9\",\"license\":\"MIT\"}},\"version\":1}", "bytecode": "0x6101006040523480156200001257600080fd5b50604051620057fa380380620057fa83398181016040528101906200003891906200067f565b838383838383838383600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603620000b3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620000aa9062000752565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250505062000108620000fc620002ee60201b60201c565b620002f660201b60201c565b80151560a0811515815250508161ffff1660c08161ffff16815250506200013583620003ba60201b60201c565b60008473ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b815260040162000170906200079a565b602060405180830381865afa1580156200018e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001b49190620007e6565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036200022b5760018442620001fb919062000847565b62000207919062000847565b600160000160086101000a81548163ffffffff021916908363ffffffff1602179055505b50505050508373ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b81526004016200026990620008a8565b602060405180830381865afa15801562000287573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002ad9190620007e6565b73ffffffffffffffffffffffffffffffffffffffff1660e08173ffffffffffffffffffffffffffffffffffffffff1681525050505050505050505062000963565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b620003ca620002ee60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16620003f06200051b60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff161462000449576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620004409062000913565b60405180910390fd5b8063ffffffff166001600001600c9054906101000a900463ffffffff1663ffffffff1603620004a4576040517f96f56f6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600001600c6101000a81548163ffffffff021916908363ffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167f02ff77a0f68d11f7efb906f331b2dda82916de8ba9c37dda2a95817936a530ec8260405162000510919062000946565b60405180910390a250565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620005768262000549565b9050919050565b60006200058a8262000569565b9050919050565b6200059c816200057d565b8114620005a857600080fd5b50565b600081519050620005bc8162000591565b92915050565b600063ffffffff82169050919050565b620005dd81620005c2565b8114620005e957600080fd5b50565b600081519050620005fd81620005d2565b92915050565b600061ffff82169050919050565b6200061c8162000603565b81146200062857600080fd5b50565b6000815190506200063c8162000611565b92915050565b60008115159050919050565b620006598162000642565b81146200066557600080fd5b50565b60008151905062000679816200064e565b92915050565b600080600080608085870312156200069c576200069b62000544565b5b6000620006ac87828801620005ab565b9450506020620006bf87828801620005ec565b9350506040620006d2878288016200062b565b9250506060620006e58782880162000668565b91505092959194509250565b600082825260208201905092915050565b7f5f726567697374727920697320656d7074790000000000000000000000000000600082015250565b60006200073a601283620006f1565b9150620007478262000702565b602082019050919050565b600060208201905081810360008301526200076d816200072b565b9050919050565b7f436861696e000000000000000000000000000000000000000000000000000000815250565b6000602082019050620007b06000830162000774565b919050565b620007c08162000569565b8114620007cc57600080fd5b50565b600081519050620007e081620007b5565b92915050565b600060208284031215620007ff57620007fe62000544565b5b60006200080f84828501620007cf565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006200085482620005c2565b91506200086183620005c2565b92508282101562000877576200087662000818565b5b828203905092915050565b7f5374616b696e6742616e6b000000000000000000000000000000000000000000815250565b6000602082019050620008be6000830162000882565b919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000620008fb602083620006f1565b91506200090882620008c3565b602082019050919050565b600060208201905081810360008301526200092e81620008ec565b9050919050565b6200094081620005c2565b82525050565b60006020820190506200095d600083018462000935565b92915050565b60805160a05160c05160e051614e02620009f860003960008181610eac015281816112260152818161145101526116880152600081816113ba015281816116650152611bd30152600061230f01526000818161082701528181610a1d01528181610ae501528181611839015281816118b00152818161194f01528181611d0b0152818161213101526122100152614e026000f3fe608060405234801561001057600080fd5b50600436106101f95760003560e01c80630f2acc3e146101fe5780630fcc0c281461022e57806317d7de7c14610238578063199dadc5146102565780631aa3a00814610286578063243b68f91461029057806324c89a49146102c057806326f3ab8b146102de57806334ba34811461030f5780633bb8819d1461032d57806340a9e5e31461035e578063485e055d1461037a5780634bc935d7146103965780634e69d560146103c657806355a373d6146103ee578063637180a81461040c5780636d046c3e1461042a578063715018a6146104485780637353cbcb1461045257806377839fe614610470578063805d34321461048e5780638d068043146104be5780638da5cb5b146104dc5780639f6119d7146104fa578063a0bc937414610518578063abf410e514610536578063adf1639d14610554578063bef9f8a114610585578063bf66e3ba146105b5578063c2a4250b146105e5578063c2b40ae414610603578063c3369db814610633578063ca4d29d214610663578063cbb1b2c714610693578063d3d3ea08146106c4578063d45167d0146106e2578063e76c0b5714610712578063e79a198f14610730578063ed9975c31461073a578063ef19f3e714610758578063f25b3f9914610788578063f2fde38b146107b8578063ffa1ad74146107d4575b600080fd5b61021860048036038101906102139190613017565b6107f2565b60405161022591906130a8565b60405180910390f35b610236610825565b005b610240610997565b60405161024d91906130a8565b60405180910390f35b610270600480360381019061026b91906131ed565b6109bf565b60405161027d91906132c3565b60405180910390f35b61028e610a1b565b005b6102aa60048036038101906102a591906132de565b610c29565b6040516102b7919061340b565b60405180910390f35b6102c8610cd2565b6040516102d591906134b5565b60405180910390f35b6102f860048036038101906102f39190613532565b610d0b565b60405161030692919061370b565b60405180910390f35b610317610eaa565b60405161032491906137c1565b60405180910390f35b610347600480360381019061034291906137dc565b610ece565b604051610355929190613831565b60405180910390f35b61037860048036038101906103739190613894565b610f63565b005b610394600480360381019061038f9190613aac565b610f73565b005b6103b060048036038101906103ab9190613bda565b611546565b6040516103bd91906132c3565b60405180910390f35b6103ce61157a565b6040516103e59b9a99989796959493929190613e5d565b60405180910390f35b6103f661181e565b6040516104039190613f3e565b60405180910390f35b61041461194b565b60405161042191906137c1565b60405180910390f35b6104326119ea565b60405161043f91906132c3565b60405180910390f35b6104506119f3565b005b61045a611a7b565b6040516104679190613f59565b60405180910390f35b610478611abe565b6040516104859190613f74565b60405180910390f35b6104a860048036038101906104a39190613f8f565b611adb565b6040516104b59190613f74565b60405180910390f35b6104c6611bcf565b6040516104d39190613fbc565b60405180910390f35b6104e4611bf7565b6040516104f19190613fd7565b60405180910390f35b610502611c20565b60405161050f9190613fd7565b60405180910390f35b610520611c3c565b60405161052d9190614069565b60405180910390f35b61053e611d09565b60405161054b91906140a5565b60405180910390f35b61056e600480360381019061056991906137dc565b611d2d565b60405161057c9291906140c0565b60405180910390f35b61059f600480360381019061059a91906140e9565b611dba565b6040516105ac91906130a8565b60405180910390f35b6105cf60048036038101906105ca91906141d9565b611ddd565b6040516105dc919061435f565b60405180910390f35b6105ed611f19565b6040516105fa9190613f59565b60405180910390f35b61061d60048036038101906106189190613f8f565b611f3c565b60405161062a91906130a8565b60405180910390f35b61064d600480360381019061064891906140e9565b611f54565b60405161065a9190613f74565b60405180910390f35b61067d60048036038101906106789190614381565b611f89565b60405161068a9190613f59565b60405180910390f35b6106ad60048036038101906106a891906137dc565b611fbd565b6040516106bb9291906143f8565b60405180910390f35b6106cc612019565b6040516106d99190613f74565b60405180910390f35b6106fc60048036038101906106f79190614421565b612036565b6040516107099190613fd7565b60405180910390f35b61071a6120f3565b6040516107279190613f74565b60405180910390f35b61073861212f565b005b6107426124b0565b60405161074f9190613fd7565b60405180910390f35b610772600480360381019061076d9190613f8f565b6124c0565b60405161077f9190613fd7565b60405180910390f35b6107a2600480360381019061079d9190613f8f565b6124f4565b6040516107af91906144b7565b60405180910390f35b6107d260048036038101906107cd91906144fe565b612531565b005b6107dc612628565b6040516107e99190613f59565b60405180910390f35b60008282604051602001610807929190614567565b60405160208183030381529060405280519060200120905092915050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156108b45750610884611bf7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156108eb576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160000160109054906101000a900460ff1615610935576040517f764c143b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018060000160106101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167fd4ae81319f0b4df100dcda9ce971671b97278c7a5ce6b37a8331a44700679fd460405160405180910390a2565b60007f436861696e000000000000000000000000000000000000000000000000000000905090565b6000610a11600260008781526020019081526020016000205484846040516020016109eb929190614567565b604051602081830303815290604052805190602001208661262d9092919063ffffffff16565b9050949350505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015610aaa5750610a7a611bf7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15610ae1576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b8152600401610b3a906145b1565b602060405180830381865afa158015610b57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7b91906145df565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610be2576040517f3a81d6fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610c1c5750610c27565b610c2581612644565b505b565b606060008267ffffffffffffffff811115610c4757610c46612eec565b5b604051908082528060200260200182016040528015610c755781602001602082028036833780820191505090505b50905060005b83811015610cc657600080602087600185010102905080880151915081848481518110610cab57610caa61460c565b5b60200260200101818152505050508080600101915050610c7b565b50809150509392505050565b6040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525081565b6060808383905067ffffffffffffffff811115610d2b57610d2a612eec565b5b604051908082528060200260200182016040528015610d595781602001602082028036833780820191505090505b5090508383905067ffffffffffffffff811115610d7957610d78612eec565b5b604051908082528060200260200182016040528015610da75781602001602082028036833780820191505090505b50915060005b84849050811015610ea257600060036000878785818110610dd157610dd061460c565b5b90506020020135815260200190815260200160002090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16848381518110610e4657610e4561460c565b5b60200260200101818152505080600001601c9054906101000a900463ffffffff16838381518110610e7a57610e7961460c565b5b602002602001019063ffffffff16908163ffffffff1681525050818060010192505050610dad565b509250929050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806000600360008581526020019081526020016000209050610f3b8160000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16612986565b81600001601c9054906101000a900463ffffffff168063ffffffff1690509250925050915091565b610f708161ffff16612a2e565b50565b610f828763ffffffff16612b79565b60008787604051602001610f97929190614692565b604051602081830303815290604052905060005b86518110156111a757858181518110610fc757610fc661460c565b5b6020026020010151868281518110610fe257610fe161460c565b5b60200260200101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff161461103f576040517f6980091000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604051806040016040528087838151811061105d5761105c61460c565b5b60200260200101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681526020018a63ffffffff16815250600360008984815181106110a9576110a861460c565b5b6020026020010151815260200190815260200160002060008201518160000160006101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff160217905550602082015181600001601c6101000a81548163ffffffff021916908363ffffffff160217905550905050818782815181106111545761115361460c565b5b602002602001015187838151811061116f5761116e61460c565b5b6020026020010151604051602001611189939291906146df565b60405160208183030381529060405291508080600101915050610fab565b506000806000838051906020012090506000805b88518110156113b7576000611220848b84815181106111dd576111dc61460c565b5b60200260200101518b85815181106111f8576111f761460c565b5b60200260200101518b86815181106112135761121261460c565b5b6020026020010151612036565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231836040518263ffffffff1660e01b815260040161127d9190613fd7565b602060405180830381865afa15801561129a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112be919061472d565b90508173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1610611325576040517f9079f69b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8193506000810361133f57828060010193505050506113b2565b868061134a90614789565b9750508173ffffffffffffffffffffffffffffffffffffffff168f63ffffffff167fbac7552ab5da8d0588709ddb75aceec28520646f54bca1cc5e6e104db61935ec8360405161139a9190613f59565b60405180910390a38086019550828060010193505050505b6111bb565b507f000000000000000000000000000000000000000000000000000000000000000061ffff16841015611416576040517fe246dc6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167f5f11830295067c4bcc7d02d4e3b048cd7427be50a3aeb6afc9d3d559ee64bcfa8d7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114de919061472d565b866040516114ee93929190614802565b60405180910390a28a600260008e63ffffffff168152602001908152602001600020819055508b600160000160086101000a81548163ffffffff021916908363ffffffff160217905550505050505050505050505050565b60008060001b830361155b5760009050611573565b61157083838661262d9092919063ffffffff16565b90505b9392505050565b6000806000806000806060806060600080600060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff1615151515815250509050439b5080606001519a50806040015198508899507f000000000000000000000000000000000000000000000000000000000000000091507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611715919061472d565b925060008067ffffffffffffffff81111561173357611732612eec565b5b6040519080825280602002602001820160405280156117615781602001602082028036833780820191505090505b5095508067ffffffffffffffff81111561177e5761177d612eec565b5b6040519080825280602002602001820160405280156117ac5781602001602082028036833780820191505090505b5096508067ffffffffffffffff8111156117c9576117c8612eec565b5b6040519080825280602002602001820160405280156117fc57816020015b60608152602001906001900390816117e75790505b50945060009850600182606001518b010197505050909192939495969798999a565b60008073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16036118ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118a590614896565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b8152600401611905906148dc565b602060405180830381865afa158015611922573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194691906145df565b905090565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b81526004016119a49061491b565b602060405180830381865afa1580156119c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e591906145df565b905090565b60006001905090565b6119fb612cf9565b73ffffffffffffffffffffffffffffffffffffffff16611a19611bf7565b73ffffffffffffffffffffffffffffffffffffffff1614611a6f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a6690614980565b60405180910390fd5b611a796000612d01565b565b6000600160000160009054906101000a900463ffffffff16600160000160049054906101000a900463ffffffff16611ab391906149a0565b63ffffffff16905090565b6000600160000160009054906101000a900463ffffffff16905090565b60008060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff161515151581525050905082816060015182604001510163ffffffff161015611bc15782915050611bca565b80604001519150505b919050565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000611c37600142611c3291906149d4565b6124c0565b905090565b611c44612e51565b60016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff161515151581525050905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060006003600085815260200190815260200160002090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681600001601c9054906101000a900463ffffffff168063ffffffff1690509250925050915091565b6000600260008363ffffffff168152602001908152602001600020549050919050565b6060815167ffffffffffffffff811115611dfa57611df9612eec565b5b604051908082528060200260200182016040528015611e285781602001602082028036833780820191505090505b5090506000805b8351811015611f0f57611ebe60026000898481518110611e5257611e5161460c565b5b602002602001015163ffffffff16815260200190815260200160002054858381518110611e8257611e8161460c565b5b6020026020010151611eaf89868a8781518110611ea257611ea161460c565b5b6020026020010151610c29565b61262d9092919063ffffffff16565b838281518110611ed157611ed061460c565b5b602002602001019015159081151581525050848181518110611ef657611ef561460c565b5b6020026020010151820191508080600101915050611e2f565b5050949350505050565b6000600160000160089054906101000a900463ffffffff1663ffffffff16905090565b60026020528060005260406000206000915090505481565b60008060001b600260008463ffffffff1681526020019081526020016000205414611f7f5781611f82565b60005b9050919050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60036020528060005260406000206000915090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169080600001601c9054906101000a900463ffffffff16905082565b6000600160000160089054906101000a900463ffffffff16905090565b6000806040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525086604051602001612081929190614a2a565b604051602081830303815290604052805190602001209050600181868686604051600081526020016040526040516120bc9493929190614a61565b6020604051602081039080840390855afa1580156120de573d6000803e3d6000fd5b50505060206040510351915050949350505050565b600080600160000160089054906101000a900463ffffffff1663ffffffff1603612120576000905061212c565b61212942611adb565b90505b90565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156121be575061218e611bf7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156121f5576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160000160109054906101000a900460ff166124ae5760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b8152600401612265906145b1565b602060405180830381865afa158015612282573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122a691906145df565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361230d576040517ff8e0084400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061244c573073ffffffffffffffffffffffffffffffffffffffff16636d046c3e6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561237d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123a19190614ad2565b15158173ffffffffffffffffffffffffffffffffffffffff16636d046c3e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124129190614ad2565b15151461244b576040517f07b72f5e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b60018060000160106101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167fd4ae81319f0b4df100dcda9ce971671b97278c7a5ce6b37a8331a44700679fd460405160405180910390a2505b565b60006124bb426124c0565b905090565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6124fc612e9a565b6040518060400160405280600260008581526020019081526020016000205481526020018363ffffffff168152509050919050565b612539612cf9565b73ffffffffffffffffffffffffffffffffffffffff16612557611bf7565b73ffffffffffffffffffffffffffffffffffffffff16146125ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125a490614980565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361261c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161261390614b71565b60405180910390fd5b61262581612d01565b50565b600281565b60008261263a8584612dc5565b1490509392505050565b6000808273ffffffffffffffffffffffffffffffffffffffff167fffa1ad74ba96b4c159a84d090433911c3991c54f629eb60d0c84aed3be5f067c60405160200161268f9190614bcc565b6040516020818303038152906040526040516126ab9190614be7565b600060405180830381855afa9150503d80600081146126e6576040519150601f19603f3d011682016040523d82523d6000602084013e6126eb565b606091505b50915091506000826126fe576001612713565b81806020019051810190612712919061472d565b5b9050600181036128935760008473ffffffffffffffffffffffffffffffffffffffff1663d3d3ea086040518163ffffffff1660e01b8152600401602060405180830381865afa15801561276a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061278e9190614c13565b90508473ffffffffffffffffffffffffffffffffffffffff1663c3369db8826040518263ffffffff1660e01b81526004016127c99190613f74565b602060405180830381865afa1580156127e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061280a9190614c13565b600160000160086101000a81548163ffffffff021916908363ffffffff16021790555060028161283a9190614c40565b600160000160046101000a81548163ffffffff021916908363ffffffff16021790555060028161286a9190614c40565b600160000160006101000a81548163ffffffff021916908363ffffffff16021790555050612980565b60008473ffffffffffffffffffffffffffffffffffffffff1663a0bc93746040518163ffffffff1660e01b815260040160a060405180830381865afa1580156128e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129049190614d0b565b90508060200151600160000160046101000a81548163ffffffff021916908363ffffffff1602179055508060200151600160000160006101000a81548163ffffffff021916908363ffffffff1602179055508060400151600160000160086101000a81548163ffffffff021916908363ffffffff160217905550505b50505050565b60008060007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff905060026001826129b99190614d38565b6129c39190614d9b565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1611612a185760008401915081601b0b92505050612a29565b600181850303915081601b0b925050505b919050565b612a36612cf9565b73ffffffffffffffffffffffffffffffffffffffff16612a54611bf7565b73ffffffffffffffffffffffffffffffffffffffff1614612aaa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612aa190614980565b60405180910390fd5b8063ffffffff166001600001600c9054906101000a900463ffffffff1663ffffffff1603612b04576040517f96f56f6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600001600c6101000a81548163ffffffff021916908363ffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167f02ff77a0f68d11f7efb906f331b2dda82916de8ba9c37dda2a95817936a530ec82604051612b6e9190613f74565b60405180910390a250565b600060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff16151515158152505090506000816040015163ffffffff1603612c81576040517f96a96e1700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81816060015182604001510163ffffffff1610612cca576040517ff886149e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001816020015101600160000160046101000a81548163ffffffff021916908363ffffffff1602179055505050565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60008082905060005b8451811015612e2f576000858281518110612dec57612deb61460c565b5b60200260200101519050808311612e0e57612e078382612e3a565b9250612e1b565b612e188184612e3a565b92505b508080612e2790614789565b915050612dce565b508091505092915050565b600082600052816020526040600020905092915050565b6040518060a00160405280600063ffffffff168152602001600063ffffffff168152602001600063ffffffff168152602001600063ffffffff1681526020016000151581525090565b604051806040016040528060008019168152602001600063ffffffff1681525090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612f2482612edb565b810181811067ffffffffffffffff82111715612f4357612f42612eec565b5b80604052505050565b6000612f56612ebd565b9050612f628282612f1b565b919050565b600067ffffffffffffffff821115612f8257612f81612eec565b5b612f8b82612edb565b9050602081019050919050565b82818337600083830152505050565b6000612fba612fb584612f67565b612f4c565b905082815260208101848484011115612fd657612fd5612ed6565b5b612fe1848285612f98565b509392505050565b600082601f830112612ffe57612ffd612ed1565b5b813561300e848260208601612fa7565b91505092915050565b6000806040838503121561302e5761302d612ec7565b5b600083013567ffffffffffffffff81111561304c5761304b612ecc565b5b61305885828601612fe9565b925050602083013567ffffffffffffffff81111561307957613078612ecc565b5b61308585828601612fe9565b9150509250929050565b6000819050919050565b6130a28161308f565b82525050565b60006020820190506130bd6000830184613099565b92915050565b6000819050919050565b6130d6816130c3565b81146130e157600080fd5b50565b6000813590506130f3816130cd565b92915050565b600067ffffffffffffffff82111561311457613113612eec565b5b602082029050602081019050919050565b600080fd5b6131338161308f565b811461313e57600080fd5b50565b6000813590506131508161312a565b92915050565b6000613169613164846130f9565b612f4c565b9050808382526020820190506020840283018581111561318c5761318b613125565b5b835b818110156131b557806131a18882613141565b84526020840193505060208101905061318e565b5050509392505050565b600082601f8301126131d4576131d3612ed1565b5b81356131e4848260208601613156565b91505092915050565b6000806000806080858703121561320757613206612ec7565b5b6000613215878288016130e4565b945050602085013567ffffffffffffffff81111561323657613235612ecc565b5b613242878288016131bf565b935050604085013567ffffffffffffffff81111561326357613262612ecc565b5b61326f87828801612fe9565b925050606085013567ffffffffffffffff8111156132905761328f612ecc565b5b61329c87828801612fe9565b91505092959194509250565b60008115159050919050565b6132bd816132a8565b82525050565b60006020820190506132d860008301846132b4565b92915050565b6000806000606084860312156132f7576132f6612ec7565b5b600084013567ffffffffffffffff81111561331557613314612ecc565b5b61332186828701612fe9565b9350506020613332868287016130e4565b9250506040613343868287016130e4565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6133828161308f565b82525050565b60006133948383613379565b60208301905092915050565b6000602082019050919050565b60006133b88261334d565b6133c28185613358565b93506133cd83613369565b8060005b838110156133fe5781516133e58882613388565b97506133f0836133a0565b9250506001810190506133d1565b5085935050505092915050565b6000602082019050818103600083015261342581846133ad565b905092915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561346757808201518184015260208101905061344c565b83811115613476576000848401525b50505050565b60006134878261342d565b6134918185613438565b93506134a1818560208601613449565b6134aa81612edb565b840191505092915050565b600060208201905081810360008301526134cf818461347c565b905092915050565b600080fd5b60008083601f8401126134f2576134f1612ed1565b5b8235905067ffffffffffffffff81111561350f5761350e6134d7565b5b60208301915083602082028301111561352b5761352a613125565b5b9250929050565b6000806020838503121561354957613548612ec7565b5b600083013567ffffffffffffffff81111561356757613566612ecc565b5b613573858286016134dc565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6135b4816130c3565b82525050565b60006135c683836135ab565b60208301905092915050565b6000602082019050919050565b60006135ea8261357f565b6135f4818561358a565b93506135ff8361359b565b8060005b8381101561363057815161361788826135ba565b9750613622836135d2565b925050600181019050613603565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600063ffffffff82169050919050565b61368281613669565b82525050565b60006136948383613679565b60208301905092915050565b6000602082019050919050565b60006136b88261363d565b6136c28185613648565b93506136cd83613659565b8060005b838110156136fe5781516136e58882613688565b97506136f0836136a0565b9250506001810190506136d1565b5085935050505092915050565b6000604082019050818103600083015261372581856135df565b9050818103602083015261373981846136ad565b90509392505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061378761378261377d84613742565b613762565b613742565b9050919050565b60006137998261376c565b9050919050565b60006137ab8261378e565b9050919050565b6137bb816137a0565b82525050565b60006020820190506137d660008301846137b2565b92915050565b6000602082840312156137f2576137f1612ec7565b5b600061380084828501613141565b91505092915050565b6000819050919050565b61381c81613809565b82525050565b61382b816130c3565b82525050565b60006040820190506138466000830185613813565b6138536020830184613822565b9392505050565b600061ffff82169050919050565b6138718161385a565b811461387c57600080fd5b50565b60008135905061388e81613868565b92915050565b6000602082840312156138aa576138a9612ec7565b5b60006138b88482850161387f565b91505092915050565b6138ca81613669565b81146138d557600080fd5b50565b6000813590506138e7816138c1565b92915050565b600067ffffffffffffffff82111561390857613907612eec565b5b602082029050602081019050919050565b600061392c613927846138ed565b612f4c565b9050808382526020820190506020840283018581111561394f5761394e613125565b5b835b81811015613978578061396488826130e4565b845260208401935050602081019050613951565b5050509392505050565b600082601f83011261399757613996612ed1565b5b81356139a7848260208601613919565b91505092915050565b600067ffffffffffffffff8211156139cb576139ca612eec565b5b602082029050602081019050919050565b600060ff82169050919050565b6139f2816139dc565b81146139fd57600080fd5b50565b600081359050613a0f816139e9565b92915050565b6000613a28613a23846139b0565b612f4c565b90508083825260208201905060208402830185811115613a4b57613a4a613125565b5b835b81811015613a745780613a608882613a00565b845260208401935050602081019050613a4d565b5050509392505050565b600082601f830112613a9357613a92612ed1565b5b8135613aa3848260208601613a15565b91505092915050565b600080600080600080600060e0888a031215613acb57613aca612ec7565b5b6000613ad98a828b016138d8565b9750506020613aea8a828b01613141565b965050604088013567ffffffffffffffff811115613b0b57613b0a612ecc565b5b613b178a828b016131bf565b955050606088013567ffffffffffffffff811115613b3857613b37612ecc565b5b613b448a828b01613982565b945050608088013567ffffffffffffffff811115613b6557613b64612ecc565b5b613b718a828b01613a7e565b93505060a088013567ffffffffffffffff811115613b9257613b91612ecc565b5b613b9e8a828b016131bf565b92505060c088013567ffffffffffffffff811115613bbf57613bbe612ecc565b5b613bcb8a828b016131bf565b91505092959891949750929550565b600080600060608486031215613bf357613bf2612ec7565b5b600084013567ffffffffffffffff811115613c1157613c10612ecc565b5b613c1d868287016131bf565b9350506020613c2e86828701613141565b9250506040613c3f86828701613141565b9150509250925092565b613c5281613669565b82525050565b6000613c6382613742565b9050919050565b613c7381613c58565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b613cae81613c58565b82525050565b6000613cc08383613ca5565b60208301905092915050565b6000602082019050919050565b6000613ce482613c79565b613cee8185613c84565b9350613cf983613c95565b8060005b83811015613d2a578151613d118882613cb4565b9750613d1c83613ccc565b925050600181019050613cfd565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b6000613d8a82613d63565b613d948185613d6e565b9350613da4818560208601613449565b613dad81612edb565b840191505092915050565b6000613dc48383613d7f565b905092915050565b6000602082019050919050565b6000613de482613d37565b613dee8185613d42565b935083602082028501613e0085613d53565b8060005b85811015613e3c5784840389528151613e1d8582613db8565b9450613e2883613dcc565b925060208a01995050600181019050613e04565b50829750879550505050505092915050565b613e578161385a565b82525050565b600061016082019050613e73600083018e613822565b613e80602083018d613c49565b613e8d604083018c613c49565b613e9a606083018b613c49565b613ea7608083018a613c6a565b613eb460a0830189613c49565b81810360c0830152613ec68188613cd9565b905081810360e0830152613eda81876135df565b9050818103610100830152613eef8186613dd9565b9050613eff610120830185613822565b613f0d610140830184613e4e565b9c9b505050505050505050505050565b6000613f288261378e565b9050919050565b613f3881613f1d565b82525050565b6000602082019050613f536000830184613f2f565b92915050565b6000602082019050613f6e6000830184613822565b92915050565b6000602082019050613f896000830184613c49565b92915050565b600060208284031215613fa557613fa4612ec7565b5b6000613fb3848285016130e4565b91505092915050565b6000602082019050613fd16000830184613e4e565b92915050565b6000602082019050613fec6000830184613c6a565b92915050565b613ffb816132a8565b82525050565b60a0820160008201516140176000850182613679565b50602082015161402a6020850182613679565b50604082015161403d6040850182613679565b5060608201516140506060850182613679565b5060808201516140636080850182613ff2565b50505050565b600060a08201905061407e6000830184614001565b92915050565b600061408f8261378e565b9050919050565b61409f81614084565b82525050565b60006020820190506140ba6000830184614096565b92915050565b60006040820190506140d56000830185613822565b6140e26020830184613822565b9392505050565b6000602082840312156140ff576140fe612ec7565b5b600061410d848285016138d8565b91505092915050565b600067ffffffffffffffff82111561413157614130612eec565b5b602082029050602081019050919050565b600061415561415084614116565b612f4c565b9050808382526020820190506020840283018581111561417857614177613125565b5b835b818110156141a1578061418d88826138d8565b84526020840193505060208101905061417a565b5050509392505050565b600082601f8301126141c0576141bf612ed1565b5b81356141d0848260208601614142565b91505092915050565b600080600080608085870312156141f3576141f2612ec7565b5b600085013567ffffffffffffffff81111561421157614210612ecc565b5b61421d878288016141ab565b945050602085013567ffffffffffffffff81111561423e5761423d612ecc565b5b61424a87828801612fe9565b935050604085013567ffffffffffffffff81111561426b5761426a612ecc565b5b61427787828801613982565b925050606085013567ffffffffffffffff81111561429857614297612ecc565b5b6142a4878288016131bf565b91505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60006142e88383613ff2565b60208301905092915050565b6000602082019050919050565b600061430c826142b0565b61431681856142bb565b9350614321836142cc565b8060005b8381101561435257815161433988826142dc565b9750614344836142f4565b925050600181019050614325565b5085935050505092915050565b600060208201905081810360008301526143798184614301565b905092915050565b6000806040838503121561439857614397612ec7565b5b60006143a6858286016130e4565b92505060206143b7858286016130e4565b9150509250929050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff82169050919050565b6143f2816143c1565b82525050565b600060408201905061440d60008301856143e9565b61441a6020830184613c49565b9392505050565b6000806000806080858703121561443b5761443a612ec7565b5b600061444987828801613141565b945050602061445a87828801613a00565b935050604061446b87828801613141565b925050606061447c87828801613141565b91505092959194509250565b60408201600082015161449e6000850182613379565b5060208201516144b16020850182613679565b50505050565b60006040820190506144cc6000830184614488565b92915050565b6144db81613c58565b81146144e657600080fd5b50565b6000813590506144f8816144d2565b92915050565b60006020828403121561451457614513612ec7565b5b6000614522848285016144e9565b91505092915050565b600081905092915050565b60006145418261342d565b61454b818561452b565b935061455b818560208601613449565b80840191505092915050565b60006145738285614536565b915061457f8284614536565b91508190509392505050565b7f436861696e000000000000000000000000000000000000000000000000000000815250565b60006020820190506145c56000830161458b565b919050565b6000815190506145d9816144d2565b92915050565b6000602082840312156145f5576145f4612ec7565b5b6000614603848285016145ca565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008160e01b9050919050565b60006146538261463b565b9050919050565b61466b61466682613669565b614648565b82525050565b6000819050919050565b61468c6146878261308f565b614671565b82525050565b600061469e828561465a565b6004820191506146ae828461467b565b6020820191508190509392505050565b6000819050919050565b6146d96146d4826130c3565b6146be565b82525050565b60006146eb8286614536565b91506146f7828561467b565b60208201915061470782846146c8565b602082019150819050949350505050565b600081519050614727816130cd565b92915050565b60006020828403121561474357614742612ec7565b5b600061475184828501614718565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614794826130c3565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036147c6576147c561475a565b5b600182019050919050565b60006147ec6147e76147e284613669565b613762565b6130c3565b9050919050565b6147fc816147d1565b82525050565b600060608201905061481760008301866147f3565b6148246020830185613822565b6148316040830184613822565b949350505050565b600082825260208201905092915050565b7f5f726567697374727920697320656d7074790000000000000000000000000000600082015250565b6000614880601283614839565b915061488b8261484a565b602082019050919050565b600060208201905081810360008301526148af81614873565b9050919050565b7f554d420000000000000000000000000000000000000000000000000000000000815250565b60006020820190506148f0600083016148b6565b919050565b7f5374616b696e6742616e6b000000000000000000000000000000000000000000815250565b600060208201905061492f600083016148f5565b919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600061496a602083614839565b915061497582614934565b602082019050919050565b600060208201905081810360008301526149998161495d565b9050919050565b60006149ab82613669565b91506149b683613669565b9250828210156149c9576149c861475a565b5b828203905092915050565b60006149df826130c3565b91506149ea836130c3565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115614a1f57614a1e61475a565b5b828201905092915050565b6000614a368285614536565b9150614a42828461467b565b6020820191508190509392505050565b614a5b816139dc565b82525050565b6000608082019050614a766000830187613099565b614a836020830186614a52565b614a906040830185613099565b614a9d6060830184613099565b95945050505050565b614aaf816132a8565b8114614aba57600080fd5b50565b600081519050614acc81614aa6565b92915050565b600060208284031215614ae857614ae7612ec7565b5b6000614af684828501614abd565b91505092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000614b5b602683614839565b9150614b6682614aff565b604082019050919050565b60006020820190508181036000830152614b8a81614b4e565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b614bc681614b91565b82525050565b6000602082019050614be16000830184614bbd565b92915050565b6000614bf38284614536565b915081905092915050565b600081519050614c0d816138c1565b92915050565b600060208284031215614c2957614c28612ec7565b5b6000614c3784828501614bfe565b91505092915050565b6000614c4b82613669565b9150614c5683613669565b92508263ffffffff03821115614c6f57614c6e61475a565b5b828201905092915050565b600080fd5b600060a08284031215614c9557614c94614c7a565b5b614c9f60a0612f4c565b90506000614caf84828501614bfe565b6000830152506020614cc384828501614bfe565b6020830152506040614cd784828501614bfe565b6040830152506060614ceb84828501614bfe565b6060830152506080614cff84828501614abd565b60808301525092915050565b600060a08284031215614d2157614d20612ec7565b5b6000614d2f84828501614c7f565b91505092915050565b6000614d43826143c1565b9150614d4e836143c1565b925082821015614d6157614d6061475a565b5b828203905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614da6826143c1565b9150614db1836143c1565b925082614dc157614dc0614d6c565b5b82820490509291505056fea2646970667358221220c360ae03d3a676b33b3c5097d3c8e8893865decc08d54266712bbb98da90469d64736f6c634300080d0033", "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101f95760003560e01c80630f2acc3e146101fe5780630fcc0c281461022e57806317d7de7c14610238578063199dadc5146102565780631aa3a00814610286578063243b68f91461029057806324c89a49146102c057806326f3ab8b146102de57806334ba34811461030f5780633bb8819d1461032d57806340a9e5e31461035e578063485e055d1461037a5780634bc935d7146103965780634e69d560146103c657806355a373d6146103ee578063637180a81461040c5780636d046c3e1461042a578063715018a6146104485780637353cbcb1461045257806377839fe614610470578063805d34321461048e5780638d068043146104be5780638da5cb5b146104dc5780639f6119d7146104fa578063a0bc937414610518578063abf410e514610536578063adf1639d14610554578063bef9f8a114610585578063bf66e3ba146105b5578063c2a4250b146105e5578063c2b40ae414610603578063c3369db814610633578063ca4d29d214610663578063cbb1b2c714610693578063d3d3ea08146106c4578063d45167d0146106e2578063e76c0b5714610712578063e79a198f14610730578063ed9975c31461073a578063ef19f3e714610758578063f25b3f9914610788578063f2fde38b146107b8578063ffa1ad74146107d4575b600080fd5b61021860048036038101906102139190613017565b6107f2565b60405161022591906130a8565b60405180910390f35b610236610825565b005b610240610997565b60405161024d91906130a8565b60405180910390f35b610270600480360381019061026b91906131ed565b6109bf565b60405161027d91906132c3565b60405180910390f35b61028e610a1b565b005b6102aa60048036038101906102a591906132de565b610c29565b6040516102b7919061340b565b60405180910390f35b6102c8610cd2565b6040516102d591906134b5565b60405180910390f35b6102f860048036038101906102f39190613532565b610d0b565b60405161030692919061370b565b60405180910390f35b610317610eaa565b60405161032491906137c1565b60405180910390f35b610347600480360381019061034291906137dc565b610ece565b604051610355929190613831565b60405180910390f35b61037860048036038101906103739190613894565b610f63565b005b610394600480360381019061038f9190613aac565b610f73565b005b6103b060048036038101906103ab9190613bda565b611546565b6040516103bd91906132c3565b60405180910390f35b6103ce61157a565b6040516103e59b9a99989796959493929190613e5d565b60405180910390f35b6103f661181e565b6040516104039190613f3e565b60405180910390f35b61041461194b565b60405161042191906137c1565b60405180910390f35b6104326119ea565b60405161043f91906132c3565b60405180910390f35b6104506119f3565b005b61045a611a7b565b6040516104679190613f59565b60405180910390f35b610478611abe565b6040516104859190613f74565b60405180910390f35b6104a860048036038101906104a39190613f8f565b611adb565b6040516104b59190613f74565b60405180910390f35b6104c6611bcf565b6040516104d39190613fbc565b60405180910390f35b6104e4611bf7565b6040516104f19190613fd7565b60405180910390f35b610502611c20565b60405161050f9190613fd7565b60405180910390f35b610520611c3c565b60405161052d9190614069565b60405180910390f35b61053e611d09565b60405161054b91906140a5565b60405180910390f35b61056e600480360381019061056991906137dc565b611d2d565b60405161057c9291906140c0565b60405180910390f35b61059f600480360381019061059a91906140e9565b611dba565b6040516105ac91906130a8565b60405180910390f35b6105cf60048036038101906105ca91906141d9565b611ddd565b6040516105dc919061435f565b60405180910390f35b6105ed611f19565b6040516105fa9190613f59565b60405180910390f35b61061d60048036038101906106189190613f8f565b611f3c565b60405161062a91906130a8565b60405180910390f35b61064d600480360381019061064891906140e9565b611f54565b60405161065a9190613f74565b60405180910390f35b61067d60048036038101906106789190614381565b611f89565b60405161068a9190613f59565b60405180910390f35b6106ad60048036038101906106a891906137dc565b611fbd565b6040516106bb9291906143f8565b60405180910390f35b6106cc612019565b6040516106d99190613f74565b60405180910390f35b6106fc60048036038101906106f79190614421565b612036565b6040516107099190613fd7565b60405180910390f35b61071a6120f3565b6040516107279190613f74565b60405180910390f35b61073861212f565b005b6107426124b0565b60405161074f9190613fd7565b60405180910390f35b610772600480360381019061076d9190613f8f565b6124c0565b60405161077f9190613fd7565b60405180910390f35b6107a2600480360381019061079d9190613f8f565b6124f4565b6040516107af91906144b7565b60405180910390f35b6107d260048036038101906107cd91906144fe565b612531565b005b6107dc612628565b6040516107e99190613f59565b60405180910390f35b60008282604051602001610807929190614567565b60405160208183030381529060405280519060200120905092915050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156108b45750610884611bf7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156108eb576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160000160109054906101000a900460ff1615610935576040517f764c143b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018060000160106101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167fd4ae81319f0b4df100dcda9ce971671b97278c7a5ce6b37a8331a44700679fd460405160405180910390a2565b60007f436861696e000000000000000000000000000000000000000000000000000000905090565b6000610a11600260008781526020019081526020016000205484846040516020016109eb929190614567565b604051602081830303815290604052805190602001208661262d9092919063ffffffff16565b9050949350505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015610aaa5750610a7a611bf7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15610ae1576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b8152600401610b3a906145b1565b602060405180830381865afa158015610b57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7b91906145df565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610be2576040517f3a81d6fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610c1c5750610c27565b610c2581612644565b505b565b606060008267ffffffffffffffff811115610c4757610c46612eec565b5b604051908082528060200260200182016040528015610c755781602001602082028036833780820191505090505b50905060005b83811015610cc657600080602087600185010102905080880151915081848481518110610cab57610caa61460c565b5b60200260200101818152505050508080600101915050610c7b565b50809150509392505050565b6040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525081565b6060808383905067ffffffffffffffff811115610d2b57610d2a612eec565b5b604051908082528060200260200182016040528015610d595781602001602082028036833780820191505090505b5090508383905067ffffffffffffffff811115610d7957610d78612eec565b5b604051908082528060200260200182016040528015610da75781602001602082028036833780820191505090505b50915060005b84849050811015610ea257600060036000878785818110610dd157610dd061460c565b5b90506020020135815260200190815260200160002090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16848381518110610e4657610e4561460c565b5b60200260200101818152505080600001601c9054906101000a900463ffffffff16838381518110610e7a57610e7961460c565b5b602002602001019063ffffffff16908163ffffffff1681525050818060010192505050610dad565b509250929050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806000600360008581526020019081526020016000209050610f3b8160000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16612986565b81600001601c9054906101000a900463ffffffff168063ffffffff1690509250925050915091565b610f708161ffff16612a2e565b50565b610f828763ffffffff16612b79565b60008787604051602001610f97929190614692565b604051602081830303815290604052905060005b86518110156111a757858181518110610fc757610fc661460c565b5b6020026020010151868281518110610fe257610fe161460c565b5b60200260200101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff161461103f576040517f6980091000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604051806040016040528087838151811061105d5761105c61460c565b5b60200260200101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681526020018a63ffffffff16815250600360008984815181106110a9576110a861460c565b5b6020026020010151815260200190815260200160002060008201518160000160006101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff160217905550602082015181600001601c6101000a81548163ffffffff021916908363ffffffff160217905550905050818782815181106111545761115361460c565b5b602002602001015187838151811061116f5761116e61460c565b5b6020026020010151604051602001611189939291906146df565b60405160208183030381529060405291508080600101915050610fab565b506000806000838051906020012090506000805b88518110156113b7576000611220848b84815181106111dd576111dc61460c565b5b60200260200101518b85815181106111f8576111f761460c565b5b60200260200101518b86815181106112135761121261460c565b5b6020026020010151612036565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231836040518263ffffffff1660e01b815260040161127d9190613fd7565b602060405180830381865afa15801561129a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112be919061472d565b90508173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1610611325576040517f9079f69b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8193506000810361133f57828060010193505050506113b2565b868061134a90614789565b9750508173ffffffffffffffffffffffffffffffffffffffff168f63ffffffff167fbac7552ab5da8d0588709ddb75aceec28520646f54bca1cc5e6e104db61935ec8360405161139a9190613f59565b60405180910390a38086019550828060010193505050505b6111bb565b507f000000000000000000000000000000000000000000000000000000000000000061ffff16841015611416576040517fe246dc6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167f5f11830295067c4bcc7d02d4e3b048cd7427be50a3aeb6afc9d3d559ee64bcfa8d7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114de919061472d565b866040516114ee93929190614802565b60405180910390a28a600260008e63ffffffff168152602001908152602001600020819055508b600160000160086101000a81548163ffffffff021916908363ffffffff160217905550505050505050505050505050565b60008060001b830361155b5760009050611573565b61157083838661262d9092919063ffffffff16565b90505b9392505050565b6000806000806000806060806060600080600060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff1615151515815250509050439b5080606001519a50806040015198508899507f000000000000000000000000000000000000000000000000000000000000000091507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611715919061472d565b925060008067ffffffffffffffff81111561173357611732612eec565b5b6040519080825280602002602001820160405280156117615781602001602082028036833780820191505090505b5095508067ffffffffffffffff81111561177e5761177d612eec565b5b6040519080825280602002602001820160405280156117ac5781602001602082028036833780820191505090505b5096508067ffffffffffffffff8111156117c9576117c8612eec565b5b6040519080825280602002602001820160405280156117fc57816020015b60608152602001906001900390816117e75790505b50945060009850600182606001518b010197505050909192939495969798999a565b60008073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16036118ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118a590614896565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b8152600401611905906148dc565b602060405180830381865afa158015611922573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194691906145df565b905090565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b81526004016119a49061491b565b602060405180830381865afa1580156119c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e591906145df565b905090565b60006001905090565b6119fb612cf9565b73ffffffffffffffffffffffffffffffffffffffff16611a19611bf7565b73ffffffffffffffffffffffffffffffffffffffff1614611a6f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a6690614980565b60405180910390fd5b611a796000612d01565b565b6000600160000160009054906101000a900463ffffffff16600160000160049054906101000a900463ffffffff16611ab391906149a0565b63ffffffff16905090565b6000600160000160009054906101000a900463ffffffff16905090565b60008060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff161515151581525050905082816060015182604001510163ffffffff161015611bc15782915050611bca565b80604001519150505b919050565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000611c37600142611c3291906149d4565b6124c0565b905090565b611c44612e51565b60016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff161515151581525050905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060006003600085815260200190815260200160002090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681600001601c9054906101000a900463ffffffff168063ffffffff1690509250925050915091565b6000600260008363ffffffff168152602001908152602001600020549050919050565b6060815167ffffffffffffffff811115611dfa57611df9612eec565b5b604051908082528060200260200182016040528015611e285781602001602082028036833780820191505090505b5090506000805b8351811015611f0f57611ebe60026000898481518110611e5257611e5161460c565b5b602002602001015163ffffffff16815260200190815260200160002054858381518110611e8257611e8161460c565b5b6020026020010151611eaf89868a8781518110611ea257611ea161460c565b5b6020026020010151610c29565b61262d9092919063ffffffff16565b838281518110611ed157611ed061460c565b5b602002602001019015159081151581525050848181518110611ef657611ef561460c565b5b6020026020010151820191508080600101915050611e2f565b5050949350505050565b6000600160000160089054906101000a900463ffffffff1663ffffffff16905090565b60026020528060005260406000206000915090505481565b60008060001b600260008463ffffffff1681526020019081526020016000205414611f7f5781611f82565b60005b9050919050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60036020528060005260406000206000915090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169080600001601c9054906101000a900463ffffffff16905082565b6000600160000160089054906101000a900463ffffffff16905090565b6000806040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525086604051602001612081929190614a2a565b604051602081830303815290604052805190602001209050600181868686604051600081526020016040526040516120bc9493929190614a61565b6020604051602081039080840390855afa1580156120de573d6000803e3d6000fd5b50505060206040510351915050949350505050565b600080600160000160089054906101000a900463ffffffff1663ffffffff1603612120576000905061212c565b61212942611adb565b90505b90565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156121be575061218e611bf7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156121f5576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160000160109054906101000a900460ff166124ae5760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b8152600401612265906145b1565b602060405180830381865afa158015612282573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122a691906145df565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361230d576040517ff8e0084400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061244c573073ffffffffffffffffffffffffffffffffffffffff16636d046c3e6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561237d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123a19190614ad2565b15158173ffffffffffffffffffffffffffffffffffffffff16636d046c3e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124129190614ad2565b15151461244b576040517f07b72f5e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b60018060000160106101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167fd4ae81319f0b4df100dcda9ce971671b97278c7a5ce6b37a8331a44700679fd460405160405180910390a2505b565b60006124bb426124c0565b905090565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6124fc612e9a565b6040518060400160405280600260008581526020019081526020016000205481526020018363ffffffff168152509050919050565b612539612cf9565b73ffffffffffffffffffffffffffffffffffffffff16612557611bf7565b73ffffffffffffffffffffffffffffffffffffffff16146125ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125a490614980565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361261c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161261390614b71565b60405180910390fd5b61262581612d01565b50565b600281565b60008261263a8584612dc5565b1490509392505050565b6000808273ffffffffffffffffffffffffffffffffffffffff167fffa1ad74ba96b4c159a84d090433911c3991c54f629eb60d0c84aed3be5f067c60405160200161268f9190614bcc565b6040516020818303038152906040526040516126ab9190614be7565b600060405180830381855afa9150503d80600081146126e6576040519150601f19603f3d011682016040523d82523d6000602084013e6126eb565b606091505b50915091506000826126fe576001612713565b81806020019051810190612712919061472d565b5b9050600181036128935760008473ffffffffffffffffffffffffffffffffffffffff1663d3d3ea086040518163ffffffff1660e01b8152600401602060405180830381865afa15801561276a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061278e9190614c13565b90508473ffffffffffffffffffffffffffffffffffffffff1663c3369db8826040518263ffffffff1660e01b81526004016127c99190613f74565b602060405180830381865afa1580156127e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061280a9190614c13565b600160000160086101000a81548163ffffffff021916908363ffffffff16021790555060028161283a9190614c40565b600160000160046101000a81548163ffffffff021916908363ffffffff16021790555060028161286a9190614c40565b600160000160006101000a81548163ffffffff021916908363ffffffff16021790555050612980565b60008473ffffffffffffffffffffffffffffffffffffffff1663a0bc93746040518163ffffffff1660e01b815260040160a060405180830381865afa1580156128e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129049190614d0b565b90508060200151600160000160046101000a81548163ffffffff021916908363ffffffff1602179055508060200151600160000160006101000a81548163ffffffff021916908363ffffffff1602179055508060400151600160000160086101000a81548163ffffffff021916908363ffffffff160217905550505b50505050565b60008060007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff905060026001826129b99190614d38565b6129c39190614d9b565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1611612a185760008401915081601b0b92505050612a29565b600181850303915081601b0b925050505b919050565b612a36612cf9565b73ffffffffffffffffffffffffffffffffffffffff16612a54611bf7565b73ffffffffffffffffffffffffffffffffffffffff1614612aaa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612aa190614980565b60405180910390fd5b8063ffffffff166001600001600c9054906101000a900463ffffffff1663ffffffff1603612b04576040517f96f56f6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600001600c6101000a81548163ffffffff021916908363ffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167f02ff77a0f68d11f7efb906f331b2dda82916de8ba9c37dda2a95817936a530ec82604051612b6e9190613f74565b60405180910390a250565b600060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff16151515158152505090506000816040015163ffffffff1603612c81576040517f96a96e1700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81816060015182604001510163ffffffff1610612cca576040517ff886149e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001816020015101600160000160046101000a81548163ffffffff021916908363ffffffff1602179055505050565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60008082905060005b8451811015612e2f576000858281518110612dec57612deb61460c565b5b60200260200101519050808311612e0e57612e078382612e3a565b9250612e1b565b612e188184612e3a565b92505b508080612e2790614789565b915050612dce565b508091505092915050565b600082600052816020526040600020905092915050565b6040518060a00160405280600063ffffffff168152602001600063ffffffff168152602001600063ffffffff168152602001600063ffffffff1681526020016000151581525090565b604051806040016040528060008019168152602001600063ffffffff1681525090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612f2482612edb565b810181811067ffffffffffffffff82111715612f4357612f42612eec565b5b80604052505050565b6000612f56612ebd565b9050612f628282612f1b565b919050565b600067ffffffffffffffff821115612f8257612f81612eec565b5b612f8b82612edb565b9050602081019050919050565b82818337600083830152505050565b6000612fba612fb584612f67565b612f4c565b905082815260208101848484011115612fd657612fd5612ed6565b5b612fe1848285612f98565b509392505050565b600082601f830112612ffe57612ffd612ed1565b5b813561300e848260208601612fa7565b91505092915050565b6000806040838503121561302e5761302d612ec7565b5b600083013567ffffffffffffffff81111561304c5761304b612ecc565b5b61305885828601612fe9565b925050602083013567ffffffffffffffff81111561307957613078612ecc565b5b61308585828601612fe9565b9150509250929050565b6000819050919050565b6130a28161308f565b82525050565b60006020820190506130bd6000830184613099565b92915050565b6000819050919050565b6130d6816130c3565b81146130e157600080fd5b50565b6000813590506130f3816130cd565b92915050565b600067ffffffffffffffff82111561311457613113612eec565b5b602082029050602081019050919050565b600080fd5b6131338161308f565b811461313e57600080fd5b50565b6000813590506131508161312a565b92915050565b6000613169613164846130f9565b612f4c565b9050808382526020820190506020840283018581111561318c5761318b613125565b5b835b818110156131b557806131a18882613141565b84526020840193505060208101905061318e565b5050509392505050565b600082601f8301126131d4576131d3612ed1565b5b81356131e4848260208601613156565b91505092915050565b6000806000806080858703121561320757613206612ec7565b5b6000613215878288016130e4565b945050602085013567ffffffffffffffff81111561323657613235612ecc565b5b613242878288016131bf565b935050604085013567ffffffffffffffff81111561326357613262612ecc565b5b61326f87828801612fe9565b925050606085013567ffffffffffffffff8111156132905761328f612ecc565b5b61329c87828801612fe9565b91505092959194509250565b60008115159050919050565b6132bd816132a8565b82525050565b60006020820190506132d860008301846132b4565b92915050565b6000806000606084860312156132f7576132f6612ec7565b5b600084013567ffffffffffffffff81111561331557613314612ecc565b5b61332186828701612fe9565b9350506020613332868287016130e4565b9250506040613343868287016130e4565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6133828161308f565b82525050565b60006133948383613379565b60208301905092915050565b6000602082019050919050565b60006133b88261334d565b6133c28185613358565b93506133cd83613369565b8060005b838110156133fe5781516133e58882613388565b97506133f0836133a0565b9250506001810190506133d1565b5085935050505092915050565b6000602082019050818103600083015261342581846133ad565b905092915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561346757808201518184015260208101905061344c565b83811115613476576000848401525b50505050565b60006134878261342d565b6134918185613438565b93506134a1818560208601613449565b6134aa81612edb565b840191505092915050565b600060208201905081810360008301526134cf818461347c565b905092915050565b600080fd5b60008083601f8401126134f2576134f1612ed1565b5b8235905067ffffffffffffffff81111561350f5761350e6134d7565b5b60208301915083602082028301111561352b5761352a613125565b5b9250929050565b6000806020838503121561354957613548612ec7565b5b600083013567ffffffffffffffff81111561356757613566612ecc565b5b613573858286016134dc565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6135b4816130c3565b82525050565b60006135c683836135ab565b60208301905092915050565b6000602082019050919050565b60006135ea8261357f565b6135f4818561358a565b93506135ff8361359b565b8060005b8381101561363057815161361788826135ba565b9750613622836135d2565b925050600181019050613603565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600063ffffffff82169050919050565b61368281613669565b82525050565b60006136948383613679565b60208301905092915050565b6000602082019050919050565b60006136b88261363d565b6136c28185613648565b93506136cd83613659565b8060005b838110156136fe5781516136e58882613688565b97506136f0836136a0565b9250506001810190506136d1565b5085935050505092915050565b6000604082019050818103600083015261372581856135df565b9050818103602083015261373981846136ad565b90509392505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061378761378261377d84613742565b613762565b613742565b9050919050565b60006137998261376c565b9050919050565b60006137ab8261378e565b9050919050565b6137bb816137a0565b82525050565b60006020820190506137d660008301846137b2565b92915050565b6000602082840312156137f2576137f1612ec7565b5b600061380084828501613141565b91505092915050565b6000819050919050565b61381c81613809565b82525050565b61382b816130c3565b82525050565b60006040820190506138466000830185613813565b6138536020830184613822565b9392505050565b600061ffff82169050919050565b6138718161385a565b811461387c57600080fd5b50565b60008135905061388e81613868565b92915050565b6000602082840312156138aa576138a9612ec7565b5b60006138b88482850161387f565b91505092915050565b6138ca81613669565b81146138d557600080fd5b50565b6000813590506138e7816138c1565b92915050565b600067ffffffffffffffff82111561390857613907612eec565b5b602082029050602081019050919050565b600061392c613927846138ed565b612f4c565b9050808382526020820190506020840283018581111561394f5761394e613125565b5b835b81811015613978578061396488826130e4565b845260208401935050602081019050613951565b5050509392505050565b600082601f83011261399757613996612ed1565b5b81356139a7848260208601613919565b91505092915050565b600067ffffffffffffffff8211156139cb576139ca612eec565b5b602082029050602081019050919050565b600060ff82169050919050565b6139f2816139dc565b81146139fd57600080fd5b50565b600081359050613a0f816139e9565b92915050565b6000613a28613a23846139b0565b612f4c565b90508083825260208201905060208402830185811115613a4b57613a4a613125565b5b835b81811015613a745780613a608882613a00565b845260208401935050602081019050613a4d565b5050509392505050565b600082601f830112613a9357613a92612ed1565b5b8135613aa3848260208601613a15565b91505092915050565b600080600080600080600060e0888a031215613acb57613aca612ec7565b5b6000613ad98a828b016138d8565b9750506020613aea8a828b01613141565b965050604088013567ffffffffffffffff811115613b0b57613b0a612ecc565b5b613b178a828b016131bf565b955050606088013567ffffffffffffffff811115613b3857613b37612ecc565b5b613b448a828b01613982565b945050608088013567ffffffffffffffff811115613b6557613b64612ecc565b5b613b718a828b01613a7e565b93505060a088013567ffffffffffffffff811115613b9257613b91612ecc565b5b613b9e8a828b016131bf565b92505060c088013567ffffffffffffffff811115613bbf57613bbe612ecc565b5b613bcb8a828b016131bf565b91505092959891949750929550565b600080600060608486031215613bf357613bf2612ec7565b5b600084013567ffffffffffffffff811115613c1157613c10612ecc565b5b613c1d868287016131bf565b9350506020613c2e86828701613141565b9250506040613c3f86828701613141565b9150509250925092565b613c5281613669565b82525050565b6000613c6382613742565b9050919050565b613c7381613c58565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b613cae81613c58565b82525050565b6000613cc08383613ca5565b60208301905092915050565b6000602082019050919050565b6000613ce482613c79565b613cee8185613c84565b9350613cf983613c95565b8060005b83811015613d2a578151613d118882613cb4565b9750613d1c83613ccc565b925050600181019050613cfd565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b6000613d8a82613d63565b613d948185613d6e565b9350613da4818560208601613449565b613dad81612edb565b840191505092915050565b6000613dc48383613d7f565b905092915050565b6000602082019050919050565b6000613de482613d37565b613dee8185613d42565b935083602082028501613e0085613d53565b8060005b85811015613e3c5784840389528151613e1d8582613db8565b9450613e2883613dcc565b925060208a01995050600181019050613e04565b50829750879550505050505092915050565b613e578161385a565b82525050565b600061016082019050613e73600083018e613822565b613e80602083018d613c49565b613e8d604083018c613c49565b613e9a606083018b613c49565b613ea7608083018a613c6a565b613eb460a0830189613c49565b81810360c0830152613ec68188613cd9565b905081810360e0830152613eda81876135df565b9050818103610100830152613eef8186613dd9565b9050613eff610120830185613822565b613f0d610140830184613e4e565b9c9b505050505050505050505050565b6000613f288261378e565b9050919050565b613f3881613f1d565b82525050565b6000602082019050613f536000830184613f2f565b92915050565b6000602082019050613f6e6000830184613822565b92915050565b6000602082019050613f896000830184613c49565b92915050565b600060208284031215613fa557613fa4612ec7565b5b6000613fb3848285016130e4565b91505092915050565b6000602082019050613fd16000830184613e4e565b92915050565b6000602082019050613fec6000830184613c6a565b92915050565b613ffb816132a8565b82525050565b60a0820160008201516140176000850182613679565b50602082015161402a6020850182613679565b50604082015161403d6040850182613679565b5060608201516140506060850182613679565b5060808201516140636080850182613ff2565b50505050565b600060a08201905061407e6000830184614001565b92915050565b600061408f8261378e565b9050919050565b61409f81614084565b82525050565b60006020820190506140ba6000830184614096565b92915050565b60006040820190506140d56000830185613822565b6140e26020830184613822565b9392505050565b6000602082840312156140ff576140fe612ec7565b5b600061410d848285016138d8565b91505092915050565b600067ffffffffffffffff82111561413157614130612eec565b5b602082029050602081019050919050565b600061415561415084614116565b612f4c565b9050808382526020820190506020840283018581111561417857614177613125565b5b835b818110156141a1578061418d88826138d8565b84526020840193505060208101905061417a565b5050509392505050565b600082601f8301126141c0576141bf612ed1565b5b81356141d0848260208601614142565b91505092915050565b600080600080608085870312156141f3576141f2612ec7565b5b600085013567ffffffffffffffff81111561421157614210612ecc565b5b61421d878288016141ab565b945050602085013567ffffffffffffffff81111561423e5761423d612ecc565b5b61424a87828801612fe9565b935050604085013567ffffffffffffffff81111561426b5761426a612ecc565b5b61427787828801613982565b925050606085013567ffffffffffffffff81111561429857614297612ecc565b5b6142a4878288016131bf565b91505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60006142e88383613ff2565b60208301905092915050565b6000602082019050919050565b600061430c826142b0565b61431681856142bb565b9350614321836142cc565b8060005b8381101561435257815161433988826142dc565b9750614344836142f4565b925050600181019050614325565b5085935050505092915050565b600060208201905081810360008301526143798184614301565b905092915050565b6000806040838503121561439857614397612ec7565b5b60006143a6858286016130e4565b92505060206143b7858286016130e4565b9150509250929050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff82169050919050565b6143f2816143c1565b82525050565b600060408201905061440d60008301856143e9565b61441a6020830184613c49565b9392505050565b6000806000806080858703121561443b5761443a612ec7565b5b600061444987828801613141565b945050602061445a87828801613a00565b935050604061446b87828801613141565b925050606061447c87828801613141565b91505092959194509250565b60408201600082015161449e6000850182613379565b5060208201516144b16020850182613679565b50505050565b60006040820190506144cc6000830184614488565b92915050565b6144db81613c58565b81146144e657600080fd5b50565b6000813590506144f8816144d2565b92915050565b60006020828403121561451457614513612ec7565b5b6000614522848285016144e9565b91505092915050565b600081905092915050565b60006145418261342d565b61454b818561452b565b935061455b818560208601613449565b80840191505092915050565b60006145738285614536565b915061457f8284614536565b91508190509392505050565b7f436861696e000000000000000000000000000000000000000000000000000000815250565b60006020820190506145c56000830161458b565b919050565b6000815190506145d9816144d2565b92915050565b6000602082840312156145f5576145f4612ec7565b5b6000614603848285016145ca565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008160e01b9050919050565b60006146538261463b565b9050919050565b61466b61466682613669565b614648565b82525050565b6000819050919050565b61468c6146878261308f565b614671565b82525050565b600061469e828561465a565b6004820191506146ae828461467b565b6020820191508190509392505050565b6000819050919050565b6146d96146d4826130c3565b6146be565b82525050565b60006146eb8286614536565b91506146f7828561467b565b60208201915061470782846146c8565b602082019150819050949350505050565b600081519050614727816130cd565b92915050565b60006020828403121561474357614742612ec7565b5b600061475184828501614718565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614794826130c3565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036147c6576147c561475a565b5b600182019050919050565b60006147ec6147e76147e284613669565b613762565b6130c3565b9050919050565b6147fc816147d1565b82525050565b600060608201905061481760008301866147f3565b6148246020830185613822565b6148316040830184613822565b949350505050565b600082825260208201905092915050565b7f5f726567697374727920697320656d7074790000000000000000000000000000600082015250565b6000614880601283614839565b915061488b8261484a565b602082019050919050565b600060208201905081810360008301526148af81614873565b9050919050565b7f554d420000000000000000000000000000000000000000000000000000000000815250565b60006020820190506148f0600083016148b6565b919050565b7f5374616b696e6742616e6b000000000000000000000000000000000000000000815250565b600060208201905061492f600083016148f5565b919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600061496a602083614839565b915061497582614934565b602082019050919050565b600060208201905081810360008301526149998161495d565b9050919050565b60006149ab82613669565b91506149b683613669565b9250828210156149c9576149c861475a565b5b828203905092915050565b60006149df826130c3565b91506149ea836130c3565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115614a1f57614a1e61475a565b5b828201905092915050565b6000614a368285614536565b9150614a42828461467b565b6020820191508190509392505050565b614a5b816139dc565b82525050565b6000608082019050614a766000830187613099565b614a836020830186614a52565b614a906040830185613099565b614a9d6060830184613099565b95945050505050565b614aaf816132a8565b8114614aba57600080fd5b50565b600081519050614acc81614aa6565b92915050565b600060208284031215614ae857614ae7612ec7565b5b6000614af684828501614abd565b91505092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000614b5b602683614839565b9150614b6682614aff565b604082019050919050565b60006020820190508181036000830152614b8a81614b4e565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b614bc681614b91565b82525050565b6000602082019050614be16000830184614bbd565b92915050565b6000614bf38284614536565b915081905092915050565b600081519050614c0d816138c1565b92915050565b600060208284031215614c2957614c28612ec7565b5b6000614c3784828501614bfe565b91505092915050565b6000614c4b82613669565b9150614c5683613669565b92508263ffffffff03821115614c6f57614c6e61475a565b5b828201905092915050565b600080fd5b600060a08284031215614c9557614c94614c7a565b5b614c9f60a0612f4c565b90506000614caf84828501614bfe565b6000830152506020614cc384828501614bfe565b6020830152506040614cd784828501614bfe565b6040830152506060614ceb84828501614bfe565b6060830152506080614cff84828501614abd565b60808301525092915050565b600060a08284031215614d2157614d20612ec7565b5b6000614d2f84828501614c7f565b91505092915050565b6000614d43826143c1565b9150614d4e836143c1565b925082821015614d6157614d6061475a565b5b828203905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614da6826143c1565b9150614db1836143c1565b925082614dc157614dc0614d6c565b5b82820490509291505056fea2646970667358221220c360ae03d3a676b33b3c5097d3c8e8893865decc08d54266712bbb98da90469d64736f6c634300080d0033", diff --git a/deployments/avalanche_production/StakingBankStatic.json b/deployments/avalanche_production/StakingBankStatic.json index 927b8d19..cd5cc738 100644 --- a/deployments/avalanche_production/StakingBankStatic.json +++ b/deployments/avalanche_production/StakingBankStatic.json @@ -1,5 +1,5 @@ { - "address": "0xb7Aa02462774f658aDef067f6999639FfeA884c6", + "address": "0xAA67E7169cDb373151f1eA0d98eA88215d950434", "abi": [ { "inputs": [ @@ -249,58 +249,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "VALIDATOR_15", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATOR_16", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATOR_17", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATOR_18", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "VALIDATOR_2", @@ -812,30 +760,30 @@ "type": "function" } ], - "transactionHash": "0x32be8b68cac11c6f1e445b9a1561a7c7f9b9955f569ecc7dc01b2bcb3ed37e62", + "transactionHash": "0x3c42fc9b59dae164a6a1ef3378f5422cca67e28fd22c52ccdee08891f2269dd7", "receipt": { "to": null, "from": "0xA6e4fFa19B213AbeA258ae72e8e1a209B9E543e7", - "contractAddress": "0xb7Aa02462774f658aDef067f6999639FfeA884c6", - "transactionIndex": 3, - "gasUsed": "2643132", + "contractAddress": "0xAA67E7169cDb373151f1eA0d98eA88215d950434", + "transactionIndex": 8, + "gasUsed": "2301671", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfb3d44b593b737f5410d34950a2a18df5f126fdadd6a8b16d43c59c950867d98", - "transactionHash": "0x32be8b68cac11c6f1e445b9a1561a7c7f9b9955f569ecc7dc01b2bcb3ed37e62", + "blockHash": "0x7ce6900a75e70ae7b5be304159e8cd55666acbd18c4e9de1f030cda4262a2f4b", + "transactionHash": "0x3c42fc9b59dae164a6a1ef3378f5422cca67e28fd22c52ccdee08891f2269dd7", "logs": [], - "blockNumber": 37447500, - "cumulativeGasUsed": "3176963", + "blockNumber": 52433372, + "cumulativeGasUsed": "3339686", "status": 1, "byzantium": true }, "args": [ - 19 + 15 ], - "numDeployments": 3, - "solcInputHash": "4db3e1d3dd51dbe508dc0a6a04352df6", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_validatorsCount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"NotSupported\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"minAmountForStake\",\"type\":\"uint256\"}],\"name\":\"LogMinAmountForStake\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"NUMBER_OF_VALIDATORS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ONE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TOTAL_SUPPLY\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_0\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_1\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_10\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_11\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_12\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_13\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_14\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_15\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_16\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_17\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_18\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_2\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_3\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_4\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_5\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_6\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_7\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_8\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_9\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_ix\",\"type\":\"uint256\"}],\"name\":\"addresses\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validator\",\"type\":\"address\"}],\"name\":\"balances\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"create\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"exit\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBalances\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"allBalances\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumberOfValidators\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"receiveApproval\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"register\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"remove\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"setMinAmountForStake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"stake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"update\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_id\",\"type\":\"address\"}],\"name\":\"validators\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"location\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_validators\",\"type\":\"address[]\"}],\"name\":\"verifyValidators\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addresses(uint256)\":{\"details\":\"gets validator address for provided index\",\"params\":{\"_ix\":\"index in array of list of all validators wallets\"}},\"balanceOf(address)\":{\"details\":\"to follow ERC20 interface\"},\"exit()\":{\"details\":\"unstake and withdraw all tokens\"},\"getName()\":{\"details\":\"to follow Registrable interface\"},\"getNumberOfValidators()\":{\"returns\":{\"_0\":\"total number of registered validators (with and without balance)\"}},\"register()\":{\"details\":\"to follow Registrable interface\"},\"totalSupply()\":{\"details\":\"to follow ERC20 interface\"},\"unregister()\":{\"details\":\"to follow Registrable interface\"},\"validators(address)\":{\"params\":{\"_id\":\"address of validator\"},\"returns\":{\"id\":\"address of validator\",\"location\":\"URL of validator\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":\"StakingBankStaticProd\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":0},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBank.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IStakingBank is IERC20 {\\n /// @param id address of validator wallet\\n /// @param location URL of the validator API\\n struct Validator {\\n address id;\\n string location;\\n }\\n\\n event LogValidatorRegistered(address indexed id);\\n event LogValidatorUpdated(address indexed id);\\n event LogValidatorRemoved(address indexed id);\\n event LogMinAmountForStake(uint256 minAmountForStake);\\n\\n /// @dev setter for `minAmountForStake`\\n function setMinAmountForStake(uint256 _minAmountForStake) external;\\n\\n /// @dev allows to stake `token` by validators\\n /// Validator needs to approve StakingBank beforehand\\n /// @param _value amount of tokens to stake\\n function stake(uint256 _value) external;\\n\\n /// @dev notification about approval from `_from` address on UMB token\\n /// Staking bank will stake max approved amount from `_from` address\\n /// @param _from address which approved token spend for IStakingBank\\n function receiveApproval(address _from) external returns (bool success);\\n\\n /// @dev withdraws stake tokens\\n /// it throws, when balance will be less than required minimum for stake\\n /// to withdraw all use `exit`\\n function withdraw(uint256 _value) external returns (bool success);\\n\\n /// @dev unstake and withdraw all tokens\\n function exit() external returns (bool success);\\n\\n /// @dev creates (register) new validator\\n /// @param _id validator address\\n /// @param _location location URL of the validator API\\n function create(address _id, string calldata _location) external;\\n\\n /// @dev removes validator\\n /// @param _id validator wallet\\n function remove(address _id) external;\\n\\n /// @dev updates validator location\\n /// @param _id validator wallet\\n /// @param _location new validator URL\\n function update(address _id, string calldata _location) external;\\n\\n /// @return total number of registered validators (with and without balance)\\n function getNumberOfValidators() external view returns (uint256);\\n\\n /// @dev gets validator address for provided index\\n /// @param _ix index in array of list of all validators wallets\\n function addresses(uint256 _ix) external view returns (address);\\n\\n /// @param _id address of validator\\n /// @return id address of validator\\n /// @return location URL of validator\\n function validators(address _id) external view returns (address id, string memory location);\\n}\\n\",\"keccak256\":\"0x2c518aeab8b0b3a364fafaec559d3ff0dc6a119f8d203fa31ef7ad667ca0f7b9\",\"license\":\"MIT\"},\"contracts/interfaces/StakingBankStaticNotSupported.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./IStakingBank.sol\\\";\\n\\nabstract contract StakingBankStaticNotSupported is IStakingBank {\\n error NotSupported();\\n\\n function create(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function update(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function remove(address) external pure {\\n revert NotSupported();\\n }\\n\\n function transfer(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function transferFrom(address, address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function receiveApproval(address) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function allowance(address, address) external pure returns (uint256) {\\n revert NotSupported();\\n }\\n\\n function approve(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function stake(uint256) external pure {\\n revert NotSupported();\\n }\\n\\n function withdraw(uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function exit() external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function setMinAmountForStake(uint256) external pure {\\n revert NotSupported();\\n }\\n}\\n\",\"keccak256\":\"0xa899ad9000220b04bc3f63f762a9a6a76dcc09449427e7774a53f4ceda9c1cf8\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStatic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"../interfaces/StakingBankStaticNotSupported.sol\\\";\\n\\n/// @dev Because we are using PoA in UMB oracle, staked balance does not matter. What's matter is, if signer is\\n/// validator or not. In this case we can optimise `StakingBank` and make it static for better gas performance.\\nabstract contract StakingBankStatic is StakingBankStaticNotSupported {\\n uint256 public constant ONE = 1e18;\\n\\n uint256 public immutable NUMBER_OF_VALIDATORS; // solhint-disable-line var-name-mixedcase\\n uint256 public immutable TOTAL_SUPPLY; // solhint-disable-line var-name-mixedcase\\n\\n constructor(uint256 _validatorsCount) {\\n NUMBER_OF_VALIDATORS = _validatorsCount;\\n TOTAL_SUPPLY = _validatorsCount * ONE;\\n\\n _assertValidSetup(_validatorsCount);\\n }\\n\\n function balances(address _validator) external view returns (uint256) {\\n return _isValidator(_validator) ? ONE : 0;\\n }\\n\\n function verifyValidators(address[] calldata _validators) external view returns (bool) {\\n for (uint256 i; i < _validators.length;) {\\n if (!_isValidator(_validators[i])) return false;\\n unchecked { i++; }\\n }\\n\\n return true;\\n }\\n\\n function getNumberOfValidators() external view returns (uint256) {\\n return NUMBER_OF_VALIDATORS;\\n }\\n\\n function getAddresses() external view returns (address[] memory) {\\n return _addresses();\\n }\\n\\n function getBalances() external view returns (uint256[] memory allBalances) {\\n allBalances = new uint256[](NUMBER_OF_VALIDATORS);\\n\\n for (uint256 i; i < NUMBER_OF_VALIDATORS;) {\\n allBalances[i] = ONE;\\n\\n unchecked {\\n // we will not have enough data to overflow\\n i++;\\n }\\n }\\n }\\n\\n function addresses(uint256 _ix) external view returns (address) {\\n return _addresses()[_ix];\\n }\\n\\n function validators(address _id) external view virtual returns (address id, string memory location);\\n\\n /// @dev to follow ERC20 interface\\n function balanceOf(address _account) external view returns (uint256) {\\n return _isValidator(_account) ? ONE : 0;\\n }\\n\\n /// @dev to follow ERC20 interface\\n function totalSupply() external view returns (uint256) {\\n return TOTAL_SUPPLY;\\n }\\n\\n /// @dev to follow Registrable interface\\n function getName() external pure returns (bytes32) {\\n return \\\"StakingBank\\\";\\n }\\n\\n /// @dev to follow Registrable interface\\n function register() external pure {\\n // there are no requirements atm\\n }\\n\\n /// @dev to follow Registrable interface\\n function unregister() external pure {\\n // there are no requirements atm\\n }\\n\\n function _addresses() internal view virtual returns (address[] memory);\\n\\n function _isValidator(address _validator) internal view virtual returns (bool);\\n\\n function _assertValidSetup(uint256 _validatorsCount) internal view virtual{\\n address[] memory list = _addresses();\\n require(list.length == _validatorsCount);\\n\\n for (uint256 i; i < _validatorsCount;) {\\n require(_isValidator(list[i]));\\n\\n unchecked { i ++; }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfcc53ff98b0f1c42e1bc7345a1535fdc4e938ef40d323600ead94b2ece59a381\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./StakingBankStatic.sol\\\";\\n\\ncontract StakingBankStaticProd is StakingBankStatic {\\n address public constant VALIDATOR_0 = 0x977Ba523420110e230643B772Fe9cF955e11dA7B;\\n address public constant VALIDATOR_1 = 0xe2422b23e52bc13ebA04d7FbB9F332Deb43360fB;\\n\\n // external order is based on validators submits on AVAX for Apr 2023\\n address public constant VALIDATOR_2 = 0x57F404aD75e371c1A539589C1eFCA12e0C6980AD;\\n address public constant VALIDATOR_3 = 0xD56C6A4f64E0bD70260472d1DB6Cf5825858CB0d;\\n address public constant VALIDATOR_4 = 0x220230Eda8f50067Dd9e4729345dabCCe0C61542;\\n address public constant VALIDATOR_5 = 0x93FdcAB283b0BcAc48157590af482E1CFd6af6aC;\\n address public constant VALIDATOR_6 = 0xCd733E06B06083d52fC5867E8E3432aA5c103A38;\\n address public constant VALIDATOR_7 = 0x42e210b110c6aa49CdfA7ceF1444Aa4719653111;\\n address public constant VALIDATOR_8 = 0x501731c6a69803a53Ec6c3e12f293c247cE1092B;\\n address public constant VALIDATOR_9 = 0x8bF9661F1b247522C75DD0FE84355aD2EfF27144;\\n address public constant VALIDATOR_10 = 0x281754Ab58391A478B7aA4E7f39991CfB41118c4;\\n address public constant VALIDATOR_11 = 0xB9C63a350A04d8BD245d18928a26EE036352dDd8;\\n address public constant VALIDATOR_12 = 0x57A51D5BDcE188c2295fCA3b4687475a54E65A02;\\n address public constant VALIDATOR_13 = 0x777FbA3666fa7747476a34577FcCC404b263E09F;\\n address public constant VALIDATOR_14 = 0x2F85824B2B38F179E451988670935d315b5b9692;\\n address public constant VALIDATOR_15 = 0xA7241994267682de4dE7Ef62f52dc2C783d1784B;\\n address public constant VALIDATOR_16 = 0x6eEd457C20603EDAE50C3A112CAA1a9425321bD0;\\n address public constant VALIDATOR_17 = 0xC5a7650c2725a7B6A39f15cb9FbffC7af357AFeb;\\n address public constant VALIDATOR_18 = 0xFEd95453678920c1b7b3A81F033Ca02a27225556;\\n\\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\\n\\n // solhint-disable-next-line code-complexity\\n function validators(address _id) external pure override returns (address id, string memory location) {\\n if (_id == VALIDATOR_0) return (_id, \\\"https://validator.umb.network\\\");\\n if (_id == VALIDATOR_1) return (_id, \\\"https://validator2.umb.network\\\");\\n if (_id == VALIDATOR_2) return (_id, \\\"https://umbrella.artemahr.tech\\\");\\n if (_id == VALIDATOR_3) return (_id, \\\"https://umb.vtabsolutions.com:3030\\\");\\n if (_id == VALIDATOR_4) return (_id, \\\"https://umb.stakers.world\\\");\\n if (_id == VALIDATOR_5) return (_id, \\\"https://umbrella.crazywhale.es\\\");\\n if (_id == VALIDATOR_6) return (_id, \\\"https://umbrella-node.gateomega.com\\\");\\n if (_id == VALIDATOR_7) return (_id, \\\"https://umb.anorak.technology\\\");\\n if (_id == VALIDATOR_8) return (_id, \\\"https://umbrella.validator.infstones.io\\\");\\n if (_id == VALIDATOR_9) return (_id, \\\"https://umb.hashquark.io\\\");\\n if (_id == VALIDATOR_10) return (_id, \\\"http://umbrella.staking4all.org:3000\\\");\\n if (_id == VALIDATOR_11) return (_id, \\\"https://umbrella-api.validatrium.club\\\");\\n if (_id == VALIDATOR_12) return (_id, \\\"http://5.161.78.230:3000\\\");\\n if (_id == VALIDATOR_13) return (_id, \\\"https://umbnode.blockchainliverpool.com\\\");\\n if (_id == VALIDATOR_14) return (_id, \\\"https://umb-api.staking.rocks\\\");\\n if (_id == VALIDATOR_15) return (_id, \\\"https://rpc.urbanhq.net\\\");\\n if (_id == VALIDATOR_16) return (_id, \\\"https://umbrella-node.ankastake.com\\\");\\n if (_id == VALIDATOR_17) return (_id, \\\"https://umbrella.tchambrella.com\\\");\\n if (_id == VALIDATOR_18) return (_id, \\\"https://umbrella-node.cmt13.eu\\\");\\n\\n return (address(0), \\\"\\\");\\n }\\n\\n function _addresses() internal view override returns (address[] memory) {\\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\\n\\n list[0] = VALIDATOR_0;\\n list[1] = VALIDATOR_1;\\n list[2] = VALIDATOR_2;\\n list[3] = VALIDATOR_3;\\n list[4] = VALIDATOR_4;\\n list[5] = VALIDATOR_5;\\n list[6] = VALIDATOR_6;\\n list[7] = VALIDATOR_7;\\n list[8] = VALIDATOR_8;\\n list[9] = VALIDATOR_9;\\n list[10] = VALIDATOR_10;\\n list[11] = VALIDATOR_11;\\n list[12] = VALIDATOR_12;\\n list[13] = VALIDATOR_13;\\n list[14] = VALIDATOR_14;\\n list[15] = VALIDATOR_15;\\n list[16] = VALIDATOR_16;\\n list[17] = VALIDATOR_17;\\n list[18] = VALIDATOR_18;\\n\\n return list;\\n }\\n\\n function _isValidator(address _validator) internal pure override returns (bool) {\\n return (\\n _validator == VALIDATOR_0\\n || _validator == VALIDATOR_1\\n || _validator == VALIDATOR_2\\n || _validator == VALIDATOR_3\\n || _validator == VALIDATOR_4\\n || _validator == VALIDATOR_5\\n || _validator == VALIDATOR_6\\n || _validator == VALIDATOR_7\\n || _validator == VALIDATOR_8\\n || _validator == VALIDATOR_9\\n || _validator == VALIDATOR_10\\n || _validator == VALIDATOR_11\\n || _validator == VALIDATOR_12\\n || _validator == VALIDATOR_13\\n || _validator == VALIDATOR_14\\n || _validator == VALIDATOR_15\\n || _validator == VALIDATOR_16\\n || _validator == VALIDATOR_17\\n || _validator == VALIDATOR_18\\n );\\n }\\n}\\n\",\"keccak256\":\"0x1e80a063f381fdb75109238bd1e4db75af37b5aea8d8165293aee4bf84838c85\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60c06040523480156200001157600080fd5b5060405162003da238038062003da2833981810160405281019062000037919062000eaf565b808060808181525050670de0b6b3a76400008162000056919062000f10565b60a081815250506200006e816200007660201b60201c565b505062000fcf565b600062000088620000ef60201b60201c565b9050818151146200009857600080fd5b60005b82811015620000ea57620000d2828281518110620000be57620000bd62000f71565b5b6020026020010151620008dd60201b60201c565b620000dc57600080fd5b80806001019150506200009b565b505050565b6060600060805167ffffffffffffffff81111562000112576200011162000fa0565b5b604051908082528060200260200182016040528015620001415781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b8160008151811062000170576200016f62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110620001d657620001d562000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad816002815181106200023c576200023b62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110620002a257620002a162000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073220230eda8f50067dd9e4729345dabcce0c615428160048151811062000308576200030762000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac816005815181106200036e576200036d62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a3881600681518110620003d457620003d362000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa4719653111816007815181106200043a576200043962000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b81600881518110620004a0576200049f62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff271448160098151811062000506576200050562000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600a815181106200056c576200056b62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073b9c63a350a04d8bd245d18928a26ee036352ddd881600b81518110620005d257620005d162000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600c8151811062000638576200063762000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073777fba3666fa7747476a34577fccc404b263e09f81600d815181106200069e576200069d62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600e8151811062000704576200070362000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600f815181106200076a576200076962000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081601081518110620007d057620007cf62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb8160118151811062000836576200083562000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073fed95453678920c1b7b3a81f033ca02a27225556816012815181106200089c576200089b62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806200096d575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80620009b857507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a03575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a4e575073220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a9957507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ae4575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b2f57507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b7a575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000bc55750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000c10575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000c5b575073b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ca657507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000cf1575073777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000d3c5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000d87575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000dd25750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000e1d575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000e68575073fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b600080fd5b6000819050919050565b62000e898162000e74565b811462000e9557600080fd5b50565b60008151905062000ea98162000e7e565b92915050565b60006020828403121562000ec85762000ec762000e6f565b5b600062000ed88482850162000e98565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600062000f1d8262000e74565b915062000f2a8362000e74565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161562000f665762000f6562000ee1565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60805160a051612d8a62001018600039600081816109ac0152610c2e01526000818161081b0152818161088901528181610c5401528181610dbd0152611db40152612d8a6000f3fe608060405234801561001057600080fd5b50600436106102195760003560e01c8062113e081461021e578063015f7ed61461023c57806303a1e2241461025a578063095ea7b3146102785780630db18e37146102a857806317d7de7c146102d857806318160ddd146102f65780631aa3a008146103145780631d4f9ce01461031e57806323b872dd1461034e57806327e235e31461037e57806329092d0e146103ae5780632e1a7d4d146103ca578063398b056e146103fa578063411ff4971461041857806345f9f8251461043657806352b41e351461045457806354755335146104705780635dc4bfd31461048e57806361a3e37e146104ac57806369dc7ae4146104ca57806370a08231146104e8578063838e7c3a14610518578063902d55a5146105345780639031d9131461055257806390ff7e2e14610570578063952c4f181461058e578063989b6996146105ac5780639f0e9484146105ca578063a15ab08d146105e8578063a39fac1214610604578063a694fc3a14610622578063a9059cbb1461063e578063b2119eac1461066e578063b49b08421461068c578063c2ee3a08146106aa578063db731777146106c8578063dd62ed3e146106e6578063e214a5fc14610716578063e29349d614610734578063e2dc7a1a14610752578063e79a198f14610770578063e985e0081461077a578063e9fad8ee14610798578063edf26d9b146107b6578063fa52c7d8146107e6575b600080fd5b610226610817565b6040516102339190612645565b60405180910390f35b6102446108e8565b60405161025191906126a8565b60405180910390f35b610262610900565b60405161026f91906126a8565b60405180910390f35b610292600480360381019061028d9190612725565b610918565b60405161029f9190612780565b60405180910390f35b6102c260048036038101906102bd919061279b565b61094c565b6040516102cf9190612780565b60405180910390f35b6102e0610980565b6040516102ed91906127e1565b60405180910390f35b6102fe6109a8565b60405161030b919061280b565b60405180910390f35b61031c6109d0565b005b6103386004803603810190610333919061288b565b6109d2565b6040516103459190612780565b60405180910390f35b610368600480360381019061036391906128d8565b610a38565b6040516103759190612780565b60405180910390f35b6103986004803603810190610393919061279b565b610a6c565b6040516103a5919061280b565b60405180910390f35b6103c860048036038101906103c3919061279b565b610a93565b005b6103e460048036038101906103df919061292b565b610ac5565b6040516103f19190612780565b60405180910390f35b610402610af9565b60405161040f91906126a8565b60405180910390f35b610420610b11565b60405161042d91906126a8565b60405180910390f35b61043e610b29565b60405161044b91906126a8565b60405180910390f35b61046e6004803603810190610469919061292b565b610b41565b005b610478610b73565b60405161048591906126a8565b60405180910390f35b610496610b8b565b6040516104a391906126a8565b60405180910390f35b6104b4610ba3565b6040516104c191906126a8565b60405180910390f35b6104d2610bbb565b6040516104df91906126a8565b60405180910390f35b61050260048036038101906104fd919061279b565b610bd3565b60405161050f919061280b565b60405180910390f35b610532600480360381019061052d91906129ae565b610bfa565b005b61053c610c2c565b604051610549919061280b565b60405180910390f35b61055a610c50565b604051610567919061280b565b60405180910390f35b610578610c78565b60405161058591906126a8565b60405180910390f35b610596610c90565b6040516105a391906126a8565b60405180910390f35b6105b4610ca8565b6040516105c191906126a8565b60405180910390f35b6105d2610cc0565b6040516105df91906126a8565b60405180910390f35b61060260048036038101906105fd91906129ae565b610cd8565b005b61060c610d0a565b6040516106199190612acc565b60405180910390f35b61063c6004803603810190610637919061292b565b610d19565b005b61065860048036038101906106539190612725565b610d4b565b6040516106659190612780565b60405180910390f35b610676610d7f565b60405161068391906126a8565b60405180910390f35b610694610d97565b6040516106a191906126a8565b60405180910390f35b6106b2610daf565b6040516106bf919061280b565b60405180910390f35b6106d0610dbb565b6040516106dd919061280b565b60405180910390f35b61070060048036038101906106fb9190612aee565b610ddf565b60405161070d919061280b565b60405180910390f35b61071e610e13565b60405161072b91906126a8565b60405180910390f35b61073c610e2b565b60405161074991906126a8565b60405180910390f35b61075a610e43565b60405161076791906126a8565b60405180910390f35b610778610e5b565b005b610782610e5d565b60405161078f91906126a8565b60405180910390f35b6107a0610e75565b6040516107ad9190612780565b60405180910390f35b6107d060048036038101906107cb919061292b565b610ea9565b6040516107dd91906126a8565b60405180910390f35b61080060048036038101906107fb919061279b565b610ed4565b60405161080e929190612bc7565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff81111561085357610852612bf7565b5b6040519080825280602002602001820160405280156108815781602001602082028036833780820191505090505b50905060005b7f00000000000000000000000000000000000000000000000000000000000000008110156108e457670de0b6b3a76400008282815181106108cb576108ca612c26565b5b6020026020010181815250508080600101915050610887565b5090565b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b83839050811015610a2c57610a118484838181106109f7576109f6612c26565b5b9050602002016020810190610a0c919061279b565b61182e565b610a1f576000915050610a32565b80806001019150506109d6565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a778261182e565b610a82576000610a8c565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b732f85824b2b38f179e451988670935d315b5b969281565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b73fed95453678920c1b7b3a81f033ca02a2722555681565b73777fba3666fa7747476a34577fccc404b263e09f81565b6000610bde8261182e565b610be9576000610bf3565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b73220230eda8f50067dd9e4729345dabcce0c6154281565b73a7241994267682de4de7ef62f52dc2c783d1784b81565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610d14611dae565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73281754ab58391a478b7aa4e7f39991cfb41118c481565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b736eed457c20603edae50c3a112caa1a9425321bd081565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b565b73b9c63a350a04d8bd245d18928a26ee036352ddd881565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610eb3611dae565b8281518110610ec557610ec4612c26565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f5f57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611829565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fe657826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611829565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361106d57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611829565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110d75782604051806060016040528060228152602001612c796022913991509150611829565b73220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361115e57826040518060400160405280601981526020017f68747470733a2f2f756d622e7374616b6572732e776f726c640000000000000081525091509150611829565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111e557826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611829565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361124f5782604051806060016040528060238152602001612c566023913991509150611829565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112d657826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611829565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113405782604051806060016040528060278152602001612cbf6027913991509150611829565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113c757826040518060400160405280601881526020017f68747470733a2f2f756d622e68617368717561726b2e696f000000000000000081525091509150611829565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114315782604051806060016040528060248152602001612c9b6024913991509150611829565b73b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361149b5782604051806060016040528060258152602001612ce66025913991509150611829565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152257826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611829565b73777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361158c5782604051806060016040528060278152602001612d2e6027913991509150611829565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361161357826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611829565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361169a57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611829565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036117045782604051806060016040528060238152602001612d0b6023913991509150611829565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361178b57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611829565b73fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361181257826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612d6e6f64652e636d7431332e6575000081525091509150611829565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806118bd575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061190757507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611951575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061199b575073220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806119e557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a2f575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a7957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ac3575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b0d5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b57575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ba1575073b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611beb57507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c35575073777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c7f5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611cc9575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d135750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d5d575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611da7575073fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff811115611dec57611deb612bf7565b5b604051908082528060200260200182016040528015611e1a5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611e4657611e45612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611ea957611ea8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611f0c57611f0b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611f6f57611f6e612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073220230eda8f50067dd9e4729345dabcce0c6154281600481518110611fd257611fd1612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac8160058151811061203557612034612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a388160068151811061209857612097612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa4719653111816007815181106120fb576120fa612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b8160088151811061215e5761215d612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff27144816009815181106121c1576121c0612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600a8151811061222457612223612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073b9c63a350a04d8bd245d18928a26ee036352ddd881600b8151811061228757612286612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600c815181106122ea576122e9612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073777fba3666fa7747476a34577fccc404b263e09f81600d8151811061234d5761234c612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600e815181106123b0576123af612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600f8151811061241357612412612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd08160108151811061247657612475612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb816011815181106124d9576124d8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073fed95453678920c1b7b3a81f033ca02a272255568160128151811061253c5761253b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6125bc816125a9565b82525050565b60006125ce83836125b3565b60208301905092915050565b6000602082019050919050565b60006125f28261257d565b6125fc8185612588565b935061260783612599565b8060005b8381101561263857815161261f88826125c2565b975061262a836125da565b92505060018101905061260b565b5085935050505092915050565b6000602082019050818103600083015261265f81846125e7565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061269282612667565b9050919050565b6126a281612687565b82525050565b60006020820190506126bd6000830184612699565b92915050565b600080fd5b600080fd5b6126d681612687565b81146126e157600080fd5b50565b6000813590506126f3816126cd565b92915050565b612702816125a9565b811461270d57600080fd5b50565b60008135905061271f816126f9565b92915050565b6000806040838503121561273c5761273b6126c3565b5b600061274a858286016126e4565b925050602061275b85828601612710565b9150509250929050565b60008115159050919050565b61277a81612765565b82525050565b60006020820190506127956000830184612771565b92915050565b6000602082840312156127b1576127b06126c3565b5b60006127bf848285016126e4565b91505092915050565b6000819050919050565b6127db816127c8565b82525050565b60006020820190506127f660008301846127d2565b92915050565b612805816125a9565b82525050565b600060208201905061282060008301846127fc565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261284b5761284a612826565b5b8235905067ffffffffffffffff8111156128685761286761282b565b5b60208301915083602082028301111561288457612883612830565b5b9250929050565b600080602083850312156128a2576128a16126c3565b5b600083013567ffffffffffffffff8111156128c0576128bf6126c8565b5b6128cc85828601612835565b92509250509250929050565b6000806000606084860312156128f1576128f06126c3565b5b60006128ff868287016126e4565b9350506020612910868287016126e4565b925050604061292186828701612710565b9150509250925092565b600060208284031215612941576129406126c3565b5b600061294f84828501612710565b91505092915050565b60008083601f84011261296e5761296d612826565b5b8235905067ffffffffffffffff81111561298b5761298a61282b565b5b6020830191508360018202830111156129a7576129a6612830565b5b9250929050565b6000806000604084860312156129c7576129c66126c3565b5b60006129d5868287016126e4565b935050602084013567ffffffffffffffff8111156129f6576129f56126c8565b5b612a0286828701612958565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b612a4381612687565b82525050565b6000612a558383612a3a565b60208301905092915050565b6000602082019050919050565b6000612a7982612a0e565b612a838185612a19565b9350612a8e83612a2a565b8060005b83811015612abf578151612aa68882612a49565b9750612ab183612a61565b925050600181019050612a92565b5085935050505092915050565b60006020820190508181036000830152612ae68184612a6e565b905092915050565b60008060408385031215612b0557612b046126c3565b5b6000612b13858286016126e4565b9250506020612b24858286016126e4565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612b68578082015181840152602081019050612b4d565b83811115612b77576000848401525b50505050565b6000601f19601f8301169050919050565b6000612b9982612b2e565b612ba38185612b39565b9350612bb3818560208601612b4a565b612bbc81612b7d565b840191505092915050565b6000604082019050612bdc6000830185612699565b8181036020830152612bee8184612b8e565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6170692e76616c696461747269756d2e636c756268747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6d68747470733a2f2f756d626e6f64652e626c6f636b636861696e6c69766572706f6f6c2e636f6da26469706673582212209a1752a9ea487818b8a4d658f151da9487c0cc92638142159bacde7ec2d21f7564736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102195760003560e01c8062113e081461021e578063015f7ed61461023c57806303a1e2241461025a578063095ea7b3146102785780630db18e37146102a857806317d7de7c146102d857806318160ddd146102f65780631aa3a008146103145780631d4f9ce01461031e57806323b872dd1461034e57806327e235e31461037e57806329092d0e146103ae5780632e1a7d4d146103ca578063398b056e146103fa578063411ff4971461041857806345f9f8251461043657806352b41e351461045457806354755335146104705780635dc4bfd31461048e57806361a3e37e146104ac57806369dc7ae4146104ca57806370a08231146104e8578063838e7c3a14610518578063902d55a5146105345780639031d9131461055257806390ff7e2e14610570578063952c4f181461058e578063989b6996146105ac5780639f0e9484146105ca578063a15ab08d146105e8578063a39fac1214610604578063a694fc3a14610622578063a9059cbb1461063e578063b2119eac1461066e578063b49b08421461068c578063c2ee3a08146106aa578063db731777146106c8578063dd62ed3e146106e6578063e214a5fc14610716578063e29349d614610734578063e2dc7a1a14610752578063e79a198f14610770578063e985e0081461077a578063e9fad8ee14610798578063edf26d9b146107b6578063fa52c7d8146107e6575b600080fd5b610226610817565b6040516102339190612645565b60405180910390f35b6102446108e8565b60405161025191906126a8565b60405180910390f35b610262610900565b60405161026f91906126a8565b60405180910390f35b610292600480360381019061028d9190612725565b610918565b60405161029f9190612780565b60405180910390f35b6102c260048036038101906102bd919061279b565b61094c565b6040516102cf9190612780565b60405180910390f35b6102e0610980565b6040516102ed91906127e1565b60405180910390f35b6102fe6109a8565b60405161030b919061280b565b60405180910390f35b61031c6109d0565b005b6103386004803603810190610333919061288b565b6109d2565b6040516103459190612780565b60405180910390f35b610368600480360381019061036391906128d8565b610a38565b6040516103759190612780565b60405180910390f35b6103986004803603810190610393919061279b565b610a6c565b6040516103a5919061280b565b60405180910390f35b6103c860048036038101906103c3919061279b565b610a93565b005b6103e460048036038101906103df919061292b565b610ac5565b6040516103f19190612780565b60405180910390f35b610402610af9565b60405161040f91906126a8565b60405180910390f35b610420610b11565b60405161042d91906126a8565b60405180910390f35b61043e610b29565b60405161044b91906126a8565b60405180910390f35b61046e6004803603810190610469919061292b565b610b41565b005b610478610b73565b60405161048591906126a8565b60405180910390f35b610496610b8b565b6040516104a391906126a8565b60405180910390f35b6104b4610ba3565b6040516104c191906126a8565b60405180910390f35b6104d2610bbb565b6040516104df91906126a8565b60405180910390f35b61050260048036038101906104fd919061279b565b610bd3565b60405161050f919061280b565b60405180910390f35b610532600480360381019061052d91906129ae565b610bfa565b005b61053c610c2c565b604051610549919061280b565b60405180910390f35b61055a610c50565b604051610567919061280b565b60405180910390f35b610578610c78565b60405161058591906126a8565b60405180910390f35b610596610c90565b6040516105a391906126a8565b60405180910390f35b6105b4610ca8565b6040516105c191906126a8565b60405180910390f35b6105d2610cc0565b6040516105df91906126a8565b60405180910390f35b61060260048036038101906105fd91906129ae565b610cd8565b005b61060c610d0a565b6040516106199190612acc565b60405180910390f35b61063c6004803603810190610637919061292b565b610d19565b005b61065860048036038101906106539190612725565b610d4b565b6040516106659190612780565b60405180910390f35b610676610d7f565b60405161068391906126a8565b60405180910390f35b610694610d97565b6040516106a191906126a8565b60405180910390f35b6106b2610daf565b6040516106bf919061280b565b60405180910390f35b6106d0610dbb565b6040516106dd919061280b565b60405180910390f35b61070060048036038101906106fb9190612aee565b610ddf565b60405161070d919061280b565b60405180910390f35b61071e610e13565b60405161072b91906126a8565b60405180910390f35b61073c610e2b565b60405161074991906126a8565b60405180910390f35b61075a610e43565b60405161076791906126a8565b60405180910390f35b610778610e5b565b005b610782610e5d565b60405161078f91906126a8565b60405180910390f35b6107a0610e75565b6040516107ad9190612780565b60405180910390f35b6107d060048036038101906107cb919061292b565b610ea9565b6040516107dd91906126a8565b60405180910390f35b61080060048036038101906107fb919061279b565b610ed4565b60405161080e929190612bc7565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff81111561085357610852612bf7565b5b6040519080825280602002602001820160405280156108815781602001602082028036833780820191505090505b50905060005b7f00000000000000000000000000000000000000000000000000000000000000008110156108e457670de0b6b3a76400008282815181106108cb576108ca612c26565b5b6020026020010181815250508080600101915050610887565b5090565b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b83839050811015610a2c57610a118484838181106109f7576109f6612c26565b5b9050602002016020810190610a0c919061279b565b61182e565b610a1f576000915050610a32565b80806001019150506109d6565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a778261182e565b610a82576000610a8c565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b732f85824b2b38f179e451988670935d315b5b969281565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b73fed95453678920c1b7b3a81f033ca02a2722555681565b73777fba3666fa7747476a34577fccc404b263e09f81565b6000610bde8261182e565b610be9576000610bf3565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b73220230eda8f50067dd9e4729345dabcce0c6154281565b73a7241994267682de4de7ef62f52dc2c783d1784b81565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610d14611dae565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73281754ab58391a478b7aa4e7f39991cfb41118c481565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b736eed457c20603edae50c3a112caa1a9425321bd081565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b565b73b9c63a350a04d8bd245d18928a26ee036352ddd881565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610eb3611dae565b8281518110610ec557610ec4612c26565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f5f57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611829565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fe657826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611829565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361106d57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611829565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110d75782604051806060016040528060228152602001612c796022913991509150611829565b73220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361115e57826040518060400160405280601981526020017f68747470733a2f2f756d622e7374616b6572732e776f726c640000000000000081525091509150611829565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111e557826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611829565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361124f5782604051806060016040528060238152602001612c566023913991509150611829565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112d657826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611829565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113405782604051806060016040528060278152602001612cbf6027913991509150611829565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113c757826040518060400160405280601881526020017f68747470733a2f2f756d622e68617368717561726b2e696f000000000000000081525091509150611829565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114315782604051806060016040528060248152602001612c9b6024913991509150611829565b73b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361149b5782604051806060016040528060258152602001612ce66025913991509150611829565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152257826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611829565b73777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361158c5782604051806060016040528060278152602001612d2e6027913991509150611829565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361161357826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611829565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361169a57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611829565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036117045782604051806060016040528060238152602001612d0b6023913991509150611829565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361178b57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611829565b73fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361181257826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612d6e6f64652e636d7431332e6575000081525091509150611829565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806118bd575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061190757507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611951575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061199b575073220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806119e557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a2f575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a7957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ac3575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b0d5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b57575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ba1575073b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611beb57507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c35575073777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c7f5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611cc9575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d135750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d5d575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611da7575073fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff811115611dec57611deb612bf7565b5b604051908082528060200260200182016040528015611e1a5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611e4657611e45612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611ea957611ea8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611f0c57611f0b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611f6f57611f6e612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073220230eda8f50067dd9e4729345dabcce0c6154281600481518110611fd257611fd1612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac8160058151811061203557612034612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a388160068151811061209857612097612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa4719653111816007815181106120fb576120fa612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b8160088151811061215e5761215d612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff27144816009815181106121c1576121c0612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600a8151811061222457612223612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073b9c63a350a04d8bd245d18928a26ee036352ddd881600b8151811061228757612286612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600c815181106122ea576122e9612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073777fba3666fa7747476a34577fccc404b263e09f81600d8151811061234d5761234c612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600e815181106123b0576123af612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600f8151811061241357612412612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd08160108151811061247657612475612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb816011815181106124d9576124d8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073fed95453678920c1b7b3a81f033ca02a272255568160128151811061253c5761253b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6125bc816125a9565b82525050565b60006125ce83836125b3565b60208301905092915050565b6000602082019050919050565b60006125f28261257d565b6125fc8185612588565b935061260783612599565b8060005b8381101561263857815161261f88826125c2565b975061262a836125da565b92505060018101905061260b565b5085935050505092915050565b6000602082019050818103600083015261265f81846125e7565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061269282612667565b9050919050565b6126a281612687565b82525050565b60006020820190506126bd6000830184612699565b92915050565b600080fd5b600080fd5b6126d681612687565b81146126e157600080fd5b50565b6000813590506126f3816126cd565b92915050565b612702816125a9565b811461270d57600080fd5b50565b60008135905061271f816126f9565b92915050565b6000806040838503121561273c5761273b6126c3565b5b600061274a858286016126e4565b925050602061275b85828601612710565b9150509250929050565b60008115159050919050565b61277a81612765565b82525050565b60006020820190506127956000830184612771565b92915050565b6000602082840312156127b1576127b06126c3565b5b60006127bf848285016126e4565b91505092915050565b6000819050919050565b6127db816127c8565b82525050565b60006020820190506127f660008301846127d2565b92915050565b612805816125a9565b82525050565b600060208201905061282060008301846127fc565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261284b5761284a612826565b5b8235905067ffffffffffffffff8111156128685761286761282b565b5b60208301915083602082028301111561288457612883612830565b5b9250929050565b600080602083850312156128a2576128a16126c3565b5b600083013567ffffffffffffffff8111156128c0576128bf6126c8565b5b6128cc85828601612835565b92509250509250929050565b6000806000606084860312156128f1576128f06126c3565b5b60006128ff868287016126e4565b9350506020612910868287016126e4565b925050604061292186828701612710565b9150509250925092565b600060208284031215612941576129406126c3565b5b600061294f84828501612710565b91505092915050565b60008083601f84011261296e5761296d612826565b5b8235905067ffffffffffffffff81111561298b5761298a61282b565b5b6020830191508360018202830111156129a7576129a6612830565b5b9250929050565b6000806000604084860312156129c7576129c66126c3565b5b60006129d5868287016126e4565b935050602084013567ffffffffffffffff8111156129f6576129f56126c8565b5b612a0286828701612958565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b612a4381612687565b82525050565b6000612a558383612a3a565b60208301905092915050565b6000602082019050919050565b6000612a7982612a0e565b612a838185612a19565b9350612a8e83612a2a565b8060005b83811015612abf578151612aa68882612a49565b9750612ab183612a61565b925050600181019050612a92565b5085935050505092915050565b60006020820190508181036000830152612ae68184612a6e565b905092915050565b60008060408385031215612b0557612b046126c3565b5b6000612b13858286016126e4565b9250506020612b24858286016126e4565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612b68578082015181840152602081019050612b4d565b83811115612b77576000848401525b50505050565b6000601f19601f8301169050919050565b6000612b9982612b2e565b612ba38185612b39565b9350612bb3818560208601612b4a565b612bbc81612b7d565b840191505092915050565b6000604082019050612bdc6000830185612699565b8181036020830152612bee8184612b8e565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6170692e76616c696461747269756d2e636c756268747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6d68747470733a2f2f756d626e6f64652e626c6f636b636861696e6c69766572706f6f6c2e636f6da26469706673582212209a1752a9ea487818b8a4d658f151da9487c0cc92638142159bacde7ec2d21f7564736f6c634300080d0033", + "numDeployments": 4, + "solcInputHash": "dc68422c0ad35a4fe46d461b096b9383", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_validatorsCount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"NotSupported\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"minAmountForStake\",\"type\":\"uint256\"}],\"name\":\"LogMinAmountForStake\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"NUMBER_OF_VALIDATORS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ONE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TOTAL_SUPPLY\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_0\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_1\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_10\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_11\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_12\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_13\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_14\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_2\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_3\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_4\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_5\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_6\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_7\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_8\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_9\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_ix\",\"type\":\"uint256\"}],\"name\":\"addresses\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validator\",\"type\":\"address\"}],\"name\":\"balances\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"create\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"exit\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBalances\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"allBalances\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumberOfValidators\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"receiveApproval\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"register\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"remove\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"setMinAmountForStake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"stake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"update\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_id\",\"type\":\"address\"}],\"name\":\"validators\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"location\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_validators\",\"type\":\"address[]\"}],\"name\":\"verifyValidators\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addresses(uint256)\":{\"details\":\"gets validator address for provided index\",\"params\":{\"_ix\":\"index in array of list of all validators wallets\"}},\"balanceOf(address)\":{\"details\":\"to follow ERC20 interface\"},\"exit()\":{\"details\":\"unstake and withdraw all tokens\"},\"getName()\":{\"details\":\"to follow Registrable interface\"},\"getNumberOfValidators()\":{\"returns\":{\"_0\":\"total number of registered validators (with and without balance)\"}},\"register()\":{\"details\":\"to follow Registrable interface\"},\"totalSupply()\":{\"details\":\"to follow ERC20 interface\"},\"unregister()\":{\"details\":\"to follow Registrable interface\"},\"validators(address)\":{\"params\":{\"_id\":\"address of validator\"},\"returns\":{\"id\":\"address of validator\",\"location\":\"URL of validator\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":\"StakingBankStaticProd\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":0},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBank.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IStakingBank is IERC20 {\\n /// @param id address of validator wallet\\n /// @param location URL of the validator API\\n struct Validator {\\n address id;\\n string location;\\n }\\n\\n event LogValidatorRegistered(address indexed id);\\n event LogValidatorUpdated(address indexed id);\\n event LogValidatorRemoved(address indexed id);\\n event LogMinAmountForStake(uint256 minAmountForStake);\\n\\n /// @dev setter for `minAmountForStake`\\n function setMinAmountForStake(uint256 _minAmountForStake) external;\\n\\n /// @dev allows to stake `token` by validators\\n /// Validator needs to approve StakingBank beforehand\\n /// @param _value amount of tokens to stake\\n function stake(uint256 _value) external;\\n\\n /// @dev notification about approval from `_from` address on UMB token\\n /// Staking bank will stake max approved amount from `_from` address\\n /// @param _from address which approved token spend for IStakingBank\\n function receiveApproval(address _from) external returns (bool success);\\n\\n /// @dev withdraws stake tokens\\n /// it throws, when balance will be less than required minimum for stake\\n /// to withdraw all use `exit`\\n function withdraw(uint256 _value) external returns (bool success);\\n\\n /// @dev unstake and withdraw all tokens\\n function exit() external returns (bool success);\\n\\n /// @dev creates (register) new validator\\n /// @param _id validator address\\n /// @param _location location URL of the validator API\\n function create(address _id, string calldata _location) external;\\n\\n /// @dev removes validator\\n /// @param _id validator wallet\\n function remove(address _id) external;\\n\\n /// @dev updates validator location\\n /// @param _id validator wallet\\n /// @param _location new validator URL\\n function update(address _id, string calldata _location) external;\\n\\n /// @return total number of registered validators (with and without balance)\\n function getNumberOfValidators() external view returns (uint256);\\n\\n /// @dev gets validator address for provided index\\n /// @param _ix index in array of list of all validators wallets\\n function addresses(uint256 _ix) external view returns (address);\\n\\n /// @param _id address of validator\\n /// @return id address of validator\\n /// @return location URL of validator\\n function validators(address _id) external view returns (address id, string memory location);\\n}\\n\",\"keccak256\":\"0x2c518aeab8b0b3a364fafaec559d3ff0dc6a119f8d203fa31ef7ad667ca0f7b9\",\"license\":\"MIT\"},\"contracts/interfaces/StakingBankStaticNotSupported.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./IStakingBank.sol\\\";\\n\\nabstract contract StakingBankStaticNotSupported is IStakingBank {\\n error NotSupported();\\n\\n function create(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function update(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function remove(address) external pure {\\n revert NotSupported();\\n }\\n\\n function transfer(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function transferFrom(address, address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function receiveApproval(address) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function allowance(address, address) external pure returns (uint256) {\\n revert NotSupported();\\n }\\n\\n function approve(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function stake(uint256) external pure {\\n revert NotSupported();\\n }\\n\\n function withdraw(uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function exit() external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function setMinAmountForStake(uint256) external pure {\\n revert NotSupported();\\n }\\n}\\n\",\"keccak256\":\"0xa899ad9000220b04bc3f63f762a9a6a76dcc09449427e7774a53f4ceda9c1cf8\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStatic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"../interfaces/StakingBankStaticNotSupported.sol\\\";\\n\\n/// @dev Because we are using PoA in UMB oracle, staked balance does not matter. What's matter is, if signer is\\n/// validator or not. In this case we can optimise `StakingBank` and make it static for better gas performance.\\nabstract contract StakingBankStatic is StakingBankStaticNotSupported {\\n uint256 public constant ONE = 1e18;\\n\\n uint256 public immutable NUMBER_OF_VALIDATORS; // solhint-disable-line var-name-mixedcase\\n uint256 public immutable TOTAL_SUPPLY; // solhint-disable-line var-name-mixedcase\\n\\n constructor(uint256 _validatorsCount) {\\n NUMBER_OF_VALIDATORS = _validatorsCount;\\n TOTAL_SUPPLY = _validatorsCount * ONE;\\n\\n _assertValidSetup(_validatorsCount);\\n }\\n\\n function balances(address _validator) external view returns (uint256) {\\n return _isValidator(_validator) ? ONE : 0;\\n }\\n\\n function verifyValidators(address[] calldata _validators) external view returns (bool) {\\n for (uint256 i; i < _validators.length;) {\\n if (!_isValidator(_validators[i])) return false;\\n unchecked { i++; }\\n }\\n\\n return true;\\n }\\n\\n function getNumberOfValidators() external view returns (uint256) {\\n return NUMBER_OF_VALIDATORS;\\n }\\n\\n function getAddresses() external view returns (address[] memory) {\\n return _addresses();\\n }\\n\\n function getBalances() external view returns (uint256[] memory allBalances) {\\n allBalances = new uint256[](NUMBER_OF_VALIDATORS);\\n\\n for (uint256 i; i < NUMBER_OF_VALIDATORS;) {\\n allBalances[i] = ONE;\\n\\n unchecked {\\n // we will not have enough data to overflow\\n i++;\\n }\\n }\\n }\\n\\n function addresses(uint256 _ix) external view returns (address) {\\n return _addresses()[_ix];\\n }\\n\\n function validators(address _id) external view virtual returns (address id, string memory location);\\n\\n /// @dev to follow ERC20 interface\\n function balanceOf(address _account) external view returns (uint256) {\\n return _isValidator(_account) ? ONE : 0;\\n }\\n\\n /// @dev to follow ERC20 interface\\n function totalSupply() external view returns (uint256) {\\n return TOTAL_SUPPLY;\\n }\\n\\n /// @dev to follow Registrable interface\\n function getName() external pure returns (bytes32) {\\n return \\\"StakingBank\\\";\\n }\\n\\n /// @dev to follow Registrable interface\\n function register() external pure {\\n // there are no requirements atm\\n }\\n\\n /// @dev to follow Registrable interface\\n function unregister() external pure {\\n // there are no requirements atm\\n }\\n\\n function _addresses() internal view virtual returns (address[] memory);\\n\\n function _isValidator(address _validator) internal view virtual returns (bool);\\n\\n function _assertValidSetup(uint256 _validatorsCount) internal view virtual{\\n address[] memory list = _addresses();\\n require(list.length == _validatorsCount);\\n\\n for (uint256 i; i < _validatorsCount;) {\\n require(_isValidator(list[i]));\\n\\n unchecked { i ++; }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfcc53ff98b0f1c42e1bc7345a1535fdc4e938ef40d323600ead94b2ece59a381\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./StakingBankStatic.sol\\\";\\n\\ncontract StakingBankStaticProd is StakingBankStatic {\\n address public constant VALIDATOR_0 = 0x977Ba523420110e230643B772Fe9cF955e11dA7B;\\n address public constant VALIDATOR_1 = 0xe2422b23e52bc13ebA04d7FbB9F332Deb43360fB;\\n\\n // external order is based on validators submits on AVAX for Apr 2023\\n address public constant VALIDATOR_2 = 0x57F404aD75e371c1A539589C1eFCA12e0C6980AD;\\n address public constant VALIDATOR_3 = 0xD56C6A4f64E0bD70260472d1DB6Cf5825858CB0d;\\n address public constant VALIDATOR_4 = 0x93FdcAB283b0BcAc48157590af482E1CFd6af6aC;\\n address public constant VALIDATOR_5 = 0xCd733E06B06083d52fC5867E8E3432aA5c103A38;\\n address public constant VALIDATOR_6 = 0x42e210b110c6aa49CdfA7ceF1444Aa4719653111;\\n address public constant VALIDATOR_7 = 0x501731c6a69803a53Ec6c3e12f293c247cE1092B;\\n address public constant VALIDATOR_8 = 0x8bF9661F1b247522C75DD0FE84355aD2EfF27144;\\n address public constant VALIDATOR_9 = 0x281754Ab58391A478B7aA4E7f39991CfB41118c4;\\n address public constant VALIDATOR_10 = 0x57A51D5BDcE188c2295fCA3b4687475a54E65A02;\\n address public constant VALIDATOR_11 = 0x2F85824B2B38F179E451988670935d315b5b9692;\\n address public constant VALIDATOR_12 = 0xA7241994267682de4dE7Ef62f52dc2C783d1784B;\\n address public constant VALIDATOR_13 = 0x6eEd457C20603EDAE50C3A112CAA1a9425321bD0;\\n address public constant VALIDATOR_14 = 0xC5a7650c2725a7B6A39f15cb9FbffC7af357AFeb;\\n\\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\\n\\n // solhint-disable-next-line code-complexity\\n function validators(address _id) external pure override returns (address id, string memory location) {\\n if (_id == VALIDATOR_0) return (_id, \\\"https://validator.umb.network\\\");\\n if (_id == VALIDATOR_1) return (_id, \\\"https://validator2.umb.network\\\");\\n if (_id == VALIDATOR_2) return (_id, \\\"https://umbrella.artemahr.tech\\\");\\n if (_id == VALIDATOR_3) return (_id, \\\"https://umb.vtabsolutions.com:3030\\\");\\n if (_id == VALIDATOR_4) return (_id, \\\"https://umbrella.crazywhale.es\\\");\\n if (_id == VALIDATOR_5) return (_id, \\\"https://umbrella-node.gateomega.com\\\");\\n if (_id == VALIDATOR_6) return (_id, \\\"https://umb.anorak.technology\\\");\\n if (_id == VALIDATOR_7) return (_id, \\\"https://umbrella.validator.infstones.io\\\");\\n if (_id == VALIDATOR_8) return (_id, \\\"https://umb.hashkey.cloud\\\");\\n if (_id == VALIDATOR_9) return (_id, \\\"http://umbrella.staking4all.org:3000\\\");\\n if (_id == VALIDATOR_10) return (_id, \\\"http://5.161.78.230:3000\\\");\\n if (_id == VALIDATOR_11) return (_id, \\\"https://umb-api.staking.rocks\\\");\\n if (_id == VALIDATOR_12) return (_id, \\\"https://rpc.urbanhq.net\\\");\\n if (_id == VALIDATOR_13) return (_id, \\\"https://umbrella-node.ankastake.com\\\");\\n if (_id == VALIDATOR_14) return (_id, \\\"https://umbrella.tchambrella.com\\\");\\n\\n return (address(0), \\\"\\\");\\n }\\n\\n function _addresses() internal view override returns (address[] memory) {\\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\\n\\n list[0] = VALIDATOR_0;\\n list[1] = VALIDATOR_1;\\n list[2] = VALIDATOR_2;\\n list[3] = VALIDATOR_3;\\n list[4] = VALIDATOR_4;\\n list[5] = VALIDATOR_5;\\n list[6] = VALIDATOR_6;\\n list[7] = VALIDATOR_7;\\n list[8] = VALIDATOR_8;\\n list[9] = VALIDATOR_9;\\n list[10] = VALIDATOR_10;\\n list[11] = VALIDATOR_11;\\n list[12] = VALIDATOR_12;\\n list[13] = VALIDATOR_13;\\n list[14] = VALIDATOR_14;\\n\\n return list;\\n }\\n\\n function _isValidator(address _validator) internal pure override returns (bool) {\\n return (\\n _validator == VALIDATOR_0\\n || _validator == VALIDATOR_1\\n || _validator == VALIDATOR_2\\n || _validator == VALIDATOR_3\\n || _validator == VALIDATOR_4\\n || _validator == VALIDATOR_5\\n || _validator == VALIDATOR_6\\n || _validator == VALIDATOR_7\\n || _validator == VALIDATOR_8\\n || _validator == VALIDATOR_9\\n || _validator == VALIDATOR_10\\n || _validator == VALIDATOR_11\\n || _validator == VALIDATOR_12\\n || _validator == VALIDATOR_13\\n || _validator == VALIDATOR_14\\n );\\n }\\n}\\n\",\"keccak256\":\"0xcf8016c7d7325800fb6ac9f7afd34804b738daded6239139b23f894855a4f98b\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c06040523480156200001157600080fd5b50604051620034f8380380620034f8833981810160405281019062000037919062000beb565b808060808181525050670de0b6b3a76400008162000056919062000c4c565b60a081815250506200006e816200007660201b60201c565b505062000d0b565b600062000088620000ef60201b60201c565b9050818151146200009857600080fd5b60005b82811015620000ea57620000d2828281518110620000be57620000bd62000cad565b5b60200260200101516200074560201b60201c565b620000dc57600080fd5b80806001019150506200009b565b505050565b6060600060805167ffffffffffffffff81111562000112576200011162000cdc565b5b604051908082528060200260200182016040528015620001415781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b8160008151811062000170576200016f62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110620001d657620001d562000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad816002815181106200023c576200023b62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110620002a257620002a162000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac8160048151811062000308576200030762000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a38816005815181106200036e576200036d62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa471965311181600681518110620003d457620003d362000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b816007815181106200043a576200043962000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff2714481600881518110620004a0576200049f62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c48160098151811062000506576200050562000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600a815181106200056c576200056b62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600b81518110620005d257620005d162000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600c8151811062000638576200063762000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081600d815181106200069e576200069d62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81600e8151811062000704576200070362000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480620007d5575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806200082057507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806200086b575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80620008b657507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000901575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806200094c57507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000997575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80620009e25750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a2d575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a7857507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ac35750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b0e575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b595750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ba4575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b600080fd5b6000819050919050565b62000bc58162000bb0565b811462000bd157600080fd5b50565b60008151905062000be58162000bba565b92915050565b60006020828403121562000c045762000c0362000bab565b5b600062000c148482850162000bd4565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600062000c598262000bb0565b915062000c668362000bb0565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161562000ca25762000ca162000c1d565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60805160a0516127a462000d54600039600081816109080152610b72015260008181610777015281816107e501528181610b9801528181610ce901526119a601526127a46000f3fe608060405234801561001057600080fd5b50600436106101ed5760003560e01c8062113e08146101f2578063015f7ed61461021057806303a1e2241461022e578063095ea7b31461024c5780630db18e371461027c57806317d7de7c146102ac57806318160ddd146102ca5780631aa3a008146102e85780631d4f9ce0146102f257806323b872dd1461032257806327e235e31461035257806329092d0e146103825780632e1a7d4d1461039e578063398b056e146103ce578063411ff497146103ec57806345f9f8251461040a57806352b41e351461042857806354755335146104445780635dc4bfd31461046257806369dc7ae41461048057806370a082311461049e578063838e7c3a146104ce578063902d55a5146104ea5780639031d9131461050857806390ff7e2e14610526578063989b6996146105445780639f0e948414610562578063a15ab08d14610580578063a39fac121461059c578063a694fc3a146105ba578063a9059cbb146105d6578063b2119eac14610606578063b49b084214610624578063c2ee3a0814610642578063db73177714610660578063dd62ed3e1461067e578063e2dc7a1a146106ae578063e79a198f146106cc578063e985e008146106d6578063e9fad8ee146106f4578063edf26d9b14610712578063fa52c7d814610742575b600080fd5b6101fa610773565b60405161020791906120ab565b60405180910390f35b610218610844565b604051610225919061210e565b60405180910390f35b61023661085c565b604051610243919061210e565b60405180910390f35b6102666004803603810190610261919061218b565b610874565b60405161027391906121e6565b60405180910390f35b61029660048036038101906102919190612201565b6108a8565b6040516102a391906121e6565b60405180910390f35b6102b46108dc565b6040516102c19190612247565b60405180910390f35b6102d2610904565b6040516102df9190612271565b60405180910390f35b6102f061092c565b005b61030c600480360381019061030791906122f1565b61092e565b60405161031991906121e6565b60405180910390f35b61033c6004803603810190610337919061233e565b610994565b60405161034991906121e6565b60405180910390f35b61036c60048036038101906103679190612201565b6109c8565b6040516103799190612271565b60405180910390f35b61039c60048036038101906103979190612201565b6109ef565b005b6103b860048036038101906103b39190612391565b610a21565b6040516103c591906121e6565b60405180910390f35b6103d6610a55565b6040516103e3919061210e565b60405180910390f35b6103f4610a6d565b604051610401919061210e565b60405180910390f35b610412610a85565b60405161041f919061210e565b60405180910390f35b610442600480360381019061043d9190612391565b610a9d565b005b61044c610acf565b604051610459919061210e565b60405180910390f35b61046a610ae7565b604051610477919061210e565b60405180910390f35b610488610aff565b604051610495919061210e565b60405180910390f35b6104b860048036038101906104b39190612201565b610b17565b6040516104c59190612271565b60405180910390f35b6104e860048036038101906104e39190612414565b610b3e565b005b6104f2610b70565b6040516104ff9190612271565b60405180910390f35b610510610b94565b60405161051d9190612271565b60405180910390f35b61052e610bbc565b60405161053b919061210e565b60405180910390f35b61054c610bd4565b604051610559919061210e565b60405180910390f35b61056a610bec565b604051610577919061210e565b60405180910390f35b61059a60048036038101906105959190612414565b610c04565b005b6105a4610c36565b6040516105b19190612532565b60405180910390f35b6105d460048036038101906105cf9190612391565b610c45565b005b6105f060048036038101906105eb919061218b565b610c77565b6040516105fd91906121e6565b60405180910390f35b61060e610cab565b60405161061b919061210e565b60405180910390f35b61062c610cc3565b604051610639919061210e565b60405180910390f35b61064a610cdb565b6040516106579190612271565b60405180910390f35b610668610ce7565b6040516106759190612271565b60405180910390f35b61069860048036038101906106939190612554565b610d0b565b6040516106a59190612271565b60405180910390f35b6106b6610d3f565b6040516106c3919061210e565b60405180910390f35b6106d4610d57565b005b6106de610d59565b6040516106eb919061210e565b60405180910390f35b6106fc610d71565b60405161070991906121e6565b60405180910390f35b61072c60048036038101906107279190612391565b610da5565b604051610739919061210e565b60405180910390f35b61075c60048036038101906107579190612201565b610dd0565b60405161076a92919061262d565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156107af576107ae61265d565b5b6040519080825280602002602001820160405280156107dd5781602001602082028036833780820191505090505b50905060005b7f000000000000000000000000000000000000000000000000000000000000000081101561084057670de0b6b3a76400008282815181106108275761082661268c565b5b60200260200101818152505080806001019150506107e3565b5090565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b838390508110156109885761096d8484838181106109535761095261268c565b5b90506020020160208101906109689190612201565b611548565b61097b57600091505061098e565b8080600101915050610932565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006109d382611548565b6109de5760006109e8565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73a7241994267682de4de7ef62f52dc2c783d1784b81565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b736eed457c20603edae50c3a112caa1a9425321bd081565b6000610b2282611548565b610b2d576000610b37565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73281754ab58391a478b7aa4e7f39991cfb41118c481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610c406119a0565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b565b732f85824b2b38f179e451988670935d315b5b969281565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610daf6119a0565b8281518110610dc157610dc061268c565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e5b57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611543565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610ee257826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611543565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f6957826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611543565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fd357826040518060600160405280602281526020016126df6022913991509150611543565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361105a57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611543565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110c457826040518060600160405280602381526020016126bc6023913991509150611543565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361114b57826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611543565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111b557826040518060600160405280602781526020016127256027913991509150611543565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361123c57826040518060400160405280601981526020017f68747470733a2f2f756d622e686173686b65792e636c6f75640000000000000081525091509150611543565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112a657826040518060600160405280602481526020016127016024913991509150611543565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361132d57826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611543565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113b457826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611543565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361143b57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611543565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114a5578260405180606001604052806023815260200161274c6023913991509150611543565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152c57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611543565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806115d7575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061162157507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061166b575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116b557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116ff575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061174957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611793575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806117dd5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611827575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061187157507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806118bb5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611905575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061194f5750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611999575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156119de576119dd61265d565b5b604051908082528060200260200182016040528015611a0c5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611a3857611a3761268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611a9b57611a9a61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611afe57611afd61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611b6157611b6061268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac81600481518110611bc457611bc361268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a3881600581518110611c2757611c2661268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa471965311181600681518110611c8a57611c8961268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b81600781518110611ced57611cec61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff2714481600881518110611d5057611d4f61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600981518110611db357611db261268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600a81518110611e1657611e1561268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600b81518110611e7957611e7861268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600c81518110611edc57611edb61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081600d81518110611f3f57611f3e61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81600e81518110611fa257611fa161268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6120228161200f565b82525050565b60006120348383612019565b60208301905092915050565b6000602082019050919050565b600061205882611fe3565b6120628185611fee565b935061206d83611fff565b8060005b8381101561209e5781516120858882612028565b975061209083612040565b925050600181019050612071565b5085935050505092915050565b600060208201905081810360008301526120c5818461204d565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006120f8826120cd565b9050919050565b612108816120ed565b82525050565b600060208201905061212360008301846120ff565b92915050565b600080fd5b600080fd5b61213c816120ed565b811461214757600080fd5b50565b60008135905061215981612133565b92915050565b6121688161200f565b811461217357600080fd5b50565b6000813590506121858161215f565b92915050565b600080604083850312156121a2576121a1612129565b5b60006121b08582860161214a565b92505060206121c185828601612176565b9150509250929050565b60008115159050919050565b6121e0816121cb565b82525050565b60006020820190506121fb60008301846121d7565b92915050565b60006020828403121561221757612216612129565b5b60006122258482850161214a565b91505092915050565b6000819050919050565b6122418161222e565b82525050565b600060208201905061225c6000830184612238565b92915050565b61226b8161200f565b82525050565b60006020820190506122866000830184612262565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126122b1576122b061228c565b5b8235905067ffffffffffffffff8111156122ce576122cd612291565b5b6020830191508360208202830111156122ea576122e9612296565b5b9250929050565b6000806020838503121561230857612307612129565b5b600083013567ffffffffffffffff8111156123265761232561212e565b5b6123328582860161229b565b92509250509250929050565b60008060006060848603121561235757612356612129565b5b60006123658682870161214a565b93505060206123768682870161214a565b925050604061238786828701612176565b9150509250925092565b6000602082840312156123a7576123a6612129565b5b60006123b584828501612176565b91505092915050565b60008083601f8401126123d4576123d361228c565b5b8235905067ffffffffffffffff8111156123f1576123f0612291565b5b60208301915083600182028301111561240d5761240c612296565b5b9250929050565b60008060006040848603121561242d5761242c612129565b5b600061243b8682870161214a565b935050602084013567ffffffffffffffff81111561245c5761245b61212e565b5b612468868287016123be565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6124a9816120ed565b82525050565b60006124bb83836124a0565b60208301905092915050565b6000602082019050919050565b60006124df82612474565b6124e9818561247f565b93506124f483612490565b8060005b8381101561252557815161250c88826124af565b9750612517836124c7565b9250506001810190506124f8565b5085935050505092915050565b6000602082019050818103600083015261254c81846124d4565b905092915050565b6000806040838503121561256b5761256a612129565b5b60006125798582860161214a565b925050602061258a8582860161214a565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156125ce5780820151818401526020810190506125b3565b838111156125dd576000848401525b50505050565b6000601f19601f8301169050919050565b60006125ff82612594565b612609818561259f565b93506126198185602086016125b0565b612622816125e3565b840191505092915050565b600060408201905061264260008301856120ff565b818103602083015261265481846125f4565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6da2646970667358221220b875faa4ff94a6ed380db1c82cfc4fcfdce28d00988b3f85c113e0332affbaa264736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101ed5760003560e01c8062113e08146101f2578063015f7ed61461021057806303a1e2241461022e578063095ea7b31461024c5780630db18e371461027c57806317d7de7c146102ac57806318160ddd146102ca5780631aa3a008146102e85780631d4f9ce0146102f257806323b872dd1461032257806327e235e31461035257806329092d0e146103825780632e1a7d4d1461039e578063398b056e146103ce578063411ff497146103ec57806345f9f8251461040a57806352b41e351461042857806354755335146104445780635dc4bfd31461046257806369dc7ae41461048057806370a082311461049e578063838e7c3a146104ce578063902d55a5146104ea5780639031d9131461050857806390ff7e2e14610526578063989b6996146105445780639f0e948414610562578063a15ab08d14610580578063a39fac121461059c578063a694fc3a146105ba578063a9059cbb146105d6578063b2119eac14610606578063b49b084214610624578063c2ee3a0814610642578063db73177714610660578063dd62ed3e1461067e578063e2dc7a1a146106ae578063e79a198f146106cc578063e985e008146106d6578063e9fad8ee146106f4578063edf26d9b14610712578063fa52c7d814610742575b600080fd5b6101fa610773565b60405161020791906120ab565b60405180910390f35b610218610844565b604051610225919061210e565b60405180910390f35b61023661085c565b604051610243919061210e565b60405180910390f35b6102666004803603810190610261919061218b565b610874565b60405161027391906121e6565b60405180910390f35b61029660048036038101906102919190612201565b6108a8565b6040516102a391906121e6565b60405180910390f35b6102b46108dc565b6040516102c19190612247565b60405180910390f35b6102d2610904565b6040516102df9190612271565b60405180910390f35b6102f061092c565b005b61030c600480360381019061030791906122f1565b61092e565b60405161031991906121e6565b60405180910390f35b61033c6004803603810190610337919061233e565b610994565b60405161034991906121e6565b60405180910390f35b61036c60048036038101906103679190612201565b6109c8565b6040516103799190612271565b60405180910390f35b61039c60048036038101906103979190612201565b6109ef565b005b6103b860048036038101906103b39190612391565b610a21565b6040516103c591906121e6565b60405180910390f35b6103d6610a55565b6040516103e3919061210e565b60405180910390f35b6103f4610a6d565b604051610401919061210e565b60405180910390f35b610412610a85565b60405161041f919061210e565b60405180910390f35b610442600480360381019061043d9190612391565b610a9d565b005b61044c610acf565b604051610459919061210e565b60405180910390f35b61046a610ae7565b604051610477919061210e565b60405180910390f35b610488610aff565b604051610495919061210e565b60405180910390f35b6104b860048036038101906104b39190612201565b610b17565b6040516104c59190612271565b60405180910390f35b6104e860048036038101906104e39190612414565b610b3e565b005b6104f2610b70565b6040516104ff9190612271565b60405180910390f35b610510610b94565b60405161051d9190612271565b60405180910390f35b61052e610bbc565b60405161053b919061210e565b60405180910390f35b61054c610bd4565b604051610559919061210e565b60405180910390f35b61056a610bec565b604051610577919061210e565b60405180910390f35b61059a60048036038101906105959190612414565b610c04565b005b6105a4610c36565b6040516105b19190612532565b60405180910390f35b6105d460048036038101906105cf9190612391565b610c45565b005b6105f060048036038101906105eb919061218b565b610c77565b6040516105fd91906121e6565b60405180910390f35b61060e610cab565b60405161061b919061210e565b60405180910390f35b61062c610cc3565b604051610639919061210e565b60405180910390f35b61064a610cdb565b6040516106579190612271565b60405180910390f35b610668610ce7565b6040516106759190612271565b60405180910390f35b61069860048036038101906106939190612554565b610d0b565b6040516106a59190612271565b60405180910390f35b6106b6610d3f565b6040516106c3919061210e565b60405180910390f35b6106d4610d57565b005b6106de610d59565b6040516106eb919061210e565b60405180910390f35b6106fc610d71565b60405161070991906121e6565b60405180910390f35b61072c60048036038101906107279190612391565b610da5565b604051610739919061210e565b60405180910390f35b61075c60048036038101906107579190612201565b610dd0565b60405161076a92919061262d565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156107af576107ae61265d565b5b6040519080825280602002602001820160405280156107dd5781602001602082028036833780820191505090505b50905060005b7f000000000000000000000000000000000000000000000000000000000000000081101561084057670de0b6b3a76400008282815181106108275761082661268c565b5b60200260200101818152505080806001019150506107e3565b5090565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b838390508110156109885761096d8484838181106109535761095261268c565b5b90506020020160208101906109689190612201565b611548565b61097b57600091505061098e565b8080600101915050610932565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006109d382611548565b6109de5760006109e8565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73a7241994267682de4de7ef62f52dc2c783d1784b81565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b736eed457c20603edae50c3a112caa1a9425321bd081565b6000610b2282611548565b610b2d576000610b37565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73281754ab58391a478b7aa4e7f39991cfb41118c481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610c406119a0565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b565b732f85824b2b38f179e451988670935d315b5b969281565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610daf6119a0565b8281518110610dc157610dc061268c565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e5b57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611543565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610ee257826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611543565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f6957826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611543565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fd357826040518060600160405280602281526020016126df6022913991509150611543565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361105a57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611543565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110c457826040518060600160405280602381526020016126bc6023913991509150611543565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361114b57826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611543565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111b557826040518060600160405280602781526020016127256027913991509150611543565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361123c57826040518060400160405280601981526020017f68747470733a2f2f756d622e686173686b65792e636c6f75640000000000000081525091509150611543565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112a657826040518060600160405280602481526020016127016024913991509150611543565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361132d57826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611543565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113b457826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611543565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361143b57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611543565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114a5578260405180606001604052806023815260200161274c6023913991509150611543565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152c57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611543565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806115d7575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061162157507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061166b575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116b557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116ff575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061174957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611793575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806117dd5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611827575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061187157507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806118bb5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611905575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061194f5750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611999575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156119de576119dd61265d565b5b604051908082528060200260200182016040528015611a0c5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611a3857611a3761268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611a9b57611a9a61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611afe57611afd61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611b6157611b6061268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac81600481518110611bc457611bc361268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a3881600581518110611c2757611c2661268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa471965311181600681518110611c8a57611c8961268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b81600781518110611ced57611cec61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff2714481600881518110611d5057611d4f61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600981518110611db357611db261268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600a81518110611e1657611e1561268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600b81518110611e7957611e7861268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600c81518110611edc57611edb61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081600d81518110611f3f57611f3e61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81600e81518110611fa257611fa161268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6120228161200f565b82525050565b60006120348383612019565b60208301905092915050565b6000602082019050919050565b600061205882611fe3565b6120628185611fee565b935061206d83611fff565b8060005b8381101561209e5781516120858882612028565b975061209083612040565b925050600181019050612071565b5085935050505092915050565b600060208201905081810360008301526120c5818461204d565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006120f8826120cd565b9050919050565b612108816120ed565b82525050565b600060208201905061212360008301846120ff565b92915050565b600080fd5b600080fd5b61213c816120ed565b811461214757600080fd5b50565b60008135905061215981612133565b92915050565b6121688161200f565b811461217357600080fd5b50565b6000813590506121858161215f565b92915050565b600080604083850312156121a2576121a1612129565b5b60006121b08582860161214a565b92505060206121c185828601612176565b9150509250929050565b60008115159050919050565b6121e0816121cb565b82525050565b60006020820190506121fb60008301846121d7565b92915050565b60006020828403121561221757612216612129565b5b60006122258482850161214a565b91505092915050565b6000819050919050565b6122418161222e565b82525050565b600060208201905061225c6000830184612238565b92915050565b61226b8161200f565b82525050565b60006020820190506122866000830184612262565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126122b1576122b061228c565b5b8235905067ffffffffffffffff8111156122ce576122cd612291565b5b6020830191508360208202830111156122ea576122e9612296565b5b9250929050565b6000806020838503121561230857612307612129565b5b600083013567ffffffffffffffff8111156123265761232561212e565b5b6123328582860161229b565b92509250509250929050565b60008060006060848603121561235757612356612129565b5b60006123658682870161214a565b93505060206123768682870161214a565b925050604061238786828701612176565b9150509250925092565b6000602082840312156123a7576123a6612129565b5b60006123b584828501612176565b91505092915050565b60008083601f8401126123d4576123d361228c565b5b8235905067ffffffffffffffff8111156123f1576123f0612291565b5b60208301915083600182028301111561240d5761240c612296565b5b9250929050565b60008060006040848603121561242d5761242c612129565b5b600061243b8682870161214a565b935050602084013567ffffffffffffffff81111561245c5761245b61212e565b5b612468868287016123be565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6124a9816120ed565b82525050565b60006124bb83836124a0565b60208301905092915050565b6000602082019050919050565b60006124df82612474565b6124e9818561247f565b93506124f483612490565b8060005b8381101561252557815161250c88826124af565b9750612517836124c7565b9250506001810190506124f8565b5085935050505092915050565b6000602082019050818103600083015261254c81846124d4565b905092915050565b6000806040838503121561256b5761256a612129565b5b60006125798582860161214a565b925050602061258a8582860161214a565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156125ce5780820151818401526020810190506125b3565b838111156125dd576000848401525b50505050565b6000601f19601f8301169050919050565b60006125ff82612594565b612609818561259f565b93506126198185602086016125b0565b612622816125e3565b840191505092915050565b600060408201905061264260008301856120ff565b818103602083015261265481846125f4565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6da2646970667358221220b875faa4ff94a6ed380db1c82cfc4fcfdce28d00988b3f85c113e0332affbaa264736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/avalanche_production/solcInputs/dc68422c0ad35a4fe46d461b096b9383.json b/deployments/avalanche_production/solcInputs/dc68422c0ad35a4fe46d461b096b9383.json new file mode 100644 index 00000000..43238985 --- /dev/null +++ b/deployments/avalanche_production/solcInputs/dc68422c0ad35a4fe46d461b096b9383.json @@ -0,0 +1,125 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n }\n _balances[to] += amount;\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n _balances[account] += amount;\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n }\n _totalSupply -= amount;\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Trees proofs.\n *\n * The proofs can be generated using the JavaScript library\n * https://github.com/miguelmota/merkletreejs[merkletreejs].\n * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.\n *\n * See `test/utils/cryptography/MerkleProof.test.js` for some examples.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(\n bytes32[] memory proof,\n bytes32 root,\n bytes32 leaf\n ) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n bytes32 proofElement = proof[i];\n if (computedHash <= proofElement) {\n // Hash(current computed hash + current element of the proof)\n computedHash = _efficientHash(computedHash, proofElement);\n } else {\n // Hash(current element of the proof + current computed hash)\n computedHash = _efficientHash(proofElement, computedHash);\n }\n }\n return computedHash;\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "@umb-network/toolbox/dist/contracts/lib/ValueDecoder.sol": { + "content": "//SPDX-License-Identifier: Unlicensed\npragma solidity >=0.6.8;\n\nlibrary ValueDecoder {\n function toUint(bytes memory _bytes) internal pure returns (uint256 value) {\n assembly {\n value := mload(add(_bytes, 32))\n }\n }\n\n function toUint(bytes32 _bytes) internal pure returns (uint256 value) {\n assembly {\n value := _bytes\n }\n }\n\n function toInt(uint224 u) internal pure returns (int256) {\n int224 i;\n uint224 max = type(uint224).max;\n\n if (u <= (max - 1) / 2) { // positive values\n assembly {\n i := add(u, 0)\n }\n\n return i;\n } else { // negative values\n assembly {\n i := sub(sub(u, max), 1)\n }\n }\n\n return i;\n }\n}\n\n" + }, + "contracts/BaseChain.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\";\nimport \"@umb-network/toolbox/dist/contracts/lib/ValueDecoder.sol\";\n\nimport \"./interfaces/IBaseChainV1.sol\";\nimport \"./interfaces/IStakingBank.sol\";\nimport \"./extensions/Registrable.sol\";\nimport \"./Registry.sol\";\n\nabstract contract BaseChain is Registrable, Ownable {\n using ValueDecoder for bytes;\n using ValueDecoder for uint224;\n using MerkleProof for bytes32[];\n\n /// @param root merkle root for consensus\n /// @param dataTimestamp consensus timestamp\n struct Block {\n bytes32 root;\n uint32 dataTimestamp;\n }\n\n /// @param value FCD value\n /// @param dataTimestamp FCD timestamp\n struct FirstClassData {\n uint224 value;\n uint32 dataTimestamp;\n }\n\n /// @param blocksCountOffset number of all blocks that were generated before switching to this contract\n /// @param sequence is a total number of blocks (consensus rounds) including previous contracts\n /// @param lastTimestamp is a timestamp of last submitted block\n /// @param padding number of seconds that need to pass before new submit will be possible\n /// @param deprecated flag that changes to TRUE on `unregister`, when TRUE submissions are not longer available\n struct ConsensusData {\n uint32 blocksCountOffset;\n uint32 sequence;\n uint32 lastTimestamp;\n uint32 padding;\n bool deprecated;\n }\n\n uint256 constant public VERSION = 2;\n\n bool internal immutable _ALLOW_FOR_MIXED_TYPE; // solhint-disable-line var-name-mixedcase\n\n bytes4 constant private _VERSION_SELECTOR = bytes4(keccak256(\"VERSION()\"));\n\n /// @dev minimal number of signatures required for accepting submission (PoA)\n uint16 internal immutable _REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\n\n ConsensusData internal _consensusData;\n\n bytes constant public ETH_PREFIX = \"\\x19Ethereum Signed Message:\\n32\";\n\n /// @dev block id (consensus ID) => root\n /// consensus ID is at the same time consensus timestamp\n mapping(uint256 => bytes32) public roots;\n\n /// @dev FCD key => FCD data\n mapping(bytes32 => FirstClassData) public fcds;\n\n event LogDeprecation(address indexed deprecator);\n event LogPadding(address indexed executor, uint32 timePadding);\n\n error ArraysDataDoNotMatch();\n error AlreadyDeprecated();\n error AlreadyRegistered();\n error BlockSubmittedToFastOrDataToOld();\n error ContractNotReady();\n error FCDOverflow();\n error InvalidContractType();\n error NoChangeToState();\n error OnlyOwnerOrRegistry();\n error UnregisterFirst();\n\n modifier onlyOwnerOrRegistry () {\n if (msg.sender != address(contractRegistry) && msg.sender != owner()) revert OnlyOwnerOrRegistry();\n _;\n }\n\n /// @param _contractRegistry Registry address\n /// @param _padding required \"space\" between blocks in seconds\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n constructor(\n IRegistry _contractRegistry,\n uint32 _padding,\n uint16 _requiredSignatures,\n bool _allowForMixedType\n ) Registrable(_contractRegistry) {\n _ALLOW_FOR_MIXED_TYPE = _allowForMixedType;\n _REQUIRED_SIGNATURES = _requiredSignatures;\n\n _setPadding(_padding);\n\n BaseChain oldChain = BaseChain(_contractRegistry.getAddress(\"Chain\"));\n\n if (address(oldChain) == address(0)) {\n // if this is first contract in sidechain, then we need to initialise lastTimestamp so submission\n // can be possible\n _consensusData.lastTimestamp = uint32(block.timestamp) - _padding - 1;\n }\n }\n\n /// @dev setter for `padding`\n function setPadding(uint16 _padding) external {\n _setPadding(_padding);\n }\n\n /// @notice if this method needs to be called manually (not from Registry)\n /// it is important to do it as part of tx batch\n /// eg using multisig, we should prepare set of transactions and confirm them all at once\n /// @inheritdoc Registrable\n function register() external override onlyOwnerOrRegistry {\n address oldChain = contractRegistry.getAddress(\"Chain\");\n\n // registration must be done before address in registry is replaced\n if (oldChain == address(this)) revert AlreadyRegistered();\n\n if (oldChain == address(0x0)) {\n return;\n }\n\n _cloneLastDataFromPrevChain(oldChain);\n }\n\n /// @inheritdoc Registrable\n function unregister() external override onlyOwnerOrRegistry {\n // in case we deprecated contract manually, we simply return\n if (_consensusData.deprecated) return;\n\n address newChain = contractRegistry.getAddress(\"Chain\");\n // unregistering must be done after address in registry is replaced\n if (newChain == address(this)) revert UnregisterFirst();\n\n // TODO:\n // I think we need to remove restriction for type (at least once)\n // when we will switch to multichain architecture\n\n if (!_ALLOW_FOR_MIXED_TYPE) {\n // can not be replaced with chain of different type\n if (BaseChain(newChain).isForeign() != this.isForeign()) revert InvalidContractType();\n }\n\n _consensusData.deprecated = true;\n emit LogDeprecation(msg.sender);\n }\n\n /// @notice it allows to deprecate contract manually\n /// Only new Registry calls `unregister()` where we set deprecated to true\n /// In old Registries we don't have this feature, so in order to safely redeploy new Chain\n /// we will have to first deprecate current contract manually, then register new contract\n function deprecate() external onlyOwnerOrRegistry {\n if (_consensusData.deprecated) revert AlreadyDeprecated();\n\n _consensusData.deprecated = true;\n emit LogDeprecation(msg.sender);\n }\n\n /// @dev getter for `_consensusData`\n function getConsensusData() external view returns (ConsensusData memory) {\n return _consensusData;\n }\n\n /// @dev number of blocks (consensus rounds) saved in this contract\n function blocksCount() external view returns (uint256) {\n return _consensusData.sequence - _consensusData.blocksCountOffset;\n }\n\n function blocksCountOffset() external view returns (uint32) {\n return _consensusData.blocksCountOffset;\n }\n\n function lastBlockId() external view returns (uint256) {\n return _consensusData.lastTimestamp;\n }\n\n /// @return TRUE if contract is ForeignChain, FALSE otherwise\n function isForeign() external pure virtual returns (bool);\n\n /// @inheritdoc Registrable\n function getName() external pure override returns (bytes32) {\n return \"Chain\";\n }\n\n /// @param _affidavit root and FCDs hashed together\n /// @param _v part of signature\n /// @param _r part of signature\n /// @param _s part of signature\n /// @return signer address\n function recoverSigner(bytes32 _affidavit, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _affidavit));\n return ecrecover(hash, _v, _r, _s);\n }\n\n /// @param _blockId ID of submitted block\n /// @return block data (root + timestamp)\n function blocks(uint256 _blockId) external view returns (Block memory) {\n return Block(roots[_blockId], uint32(_blockId));\n }\n\n /// @return current block ID\n /// please note, that current ID is not the same as last ID, current means that once padding pass,\n /// ID will switch to next one and it will be pointing to empty submit until submit for that ID is done\n function getBlockId() external view returns (uint32) {\n if (_consensusData.lastTimestamp == 0) return 0;\n\n return getBlockIdAtTimestamp(block.timestamp);\n }\n\n function requiredSignatures() external view returns (uint16) {\n return _REQUIRED_SIGNATURES;\n }\n\n /// @dev calculates block ID for provided timestamp\n /// this function does not works for past timestamps\n /// @param _timestamp current or future timestamp\n /// @return block ID for provided timestamp\n function getBlockIdAtTimestamp(uint256 _timestamp) virtual public view returns (uint32) {\n ConsensusData memory data = _consensusData;\n\n unchecked {\n // we can't overflow because we adding two `uint32`\n if (data.lastTimestamp + data.padding < _timestamp) {\n return uint32(_timestamp);\n }\n }\n\n return data.lastTimestamp;\n }\n\n /// @return last submitted block ID, please note, that on deployment, when there is no submission for this contract\n /// block for last ID will be available in previous contract\n function getLatestBlockId() virtual public view returns (uint32) {\n return _consensusData.lastTimestamp;\n }\n\n /// @dev verifies if the leaf is valid leaf for merkle tree\n /// @param _proof merkle proof for merkle tree\n /// @param _root merkle root\n /// @param _leaf leaf hash\n /// @return TRUE if `_leaf` is valid, FALSE otherwise\n function verifyProof(bytes32[] memory _proof, bytes32 _root, bytes32 _leaf) public pure returns (bool) {\n if (_root == bytes32(0)) {\n return false;\n }\n\n return _proof.verify(_root, _leaf);\n }\n\n /// @dev creates leaf hash, that has is used in merkle tree\n /// @param _key key under which we store the value\n /// @param _value value itself as bytes\n /// @return leaf hash\n function hashLeaf(bytes memory _key, bytes memory _value) public pure returns (bytes32) {\n return keccak256(abi.encodePacked(_key, _value));\n }\n\n /// @dev verifies, if provided key-value pair was part of consensus\n /// @param _blockId consensus ID for which we doing a check\n /// @param _proof merkle proof for pair\n /// @param _key pair key\n /// @param _value pair value\n /// @return TRUE if key-value par was part of consensus, FALSE otherwise\n function verifyProofForBlock(\n uint256 _blockId,\n bytes32[] memory _proof,\n bytes memory _key,\n bytes memory _value\n )\n public\n view\n returns (bool)\n {\n return _proof.verify(roots[_blockId], keccak256(abi.encodePacked(_key, _value)));\n }\n\n /// @dev this is helper method, that extracts one merkle proof from many hashed provided as bytes\n /// @param _data many hashes as bytes\n /// @param _offset this is starting point for extraction\n /// @param _items how many hashes to extract\n /// @return merkle proof (array of bytes32 hashes)\n function bytesToBytes32Array(\n bytes memory _data,\n uint256 _offset,\n uint256 _items\n )\n public\n pure\n returns (bytes32[] memory)\n {\n bytes32[] memory dataList = new bytes32[](_items);\n\n // we can unchecked because we working only with `i` and `_offset`\n // in case of wrong `_offset` it will throw\n unchecked {\n for (uint256 i = 0; i < _items; i++) {\n bytes32 temp;\n uint256 idx = (i + 1 + _offset) * 32;\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n temp := mload(add(_data, idx))\n }\n\n dataList[i] = temp;\n }\n }\n\n return (dataList);\n }\n\n /// @dev batch method for data verification\n /// @param _blockIds consensus IDs for which we doing a checks\n /// @param _proofs merkle proofs for all pair, sequence of hashes provided as bytes\n /// @param _proofItemsCounter array of counters, each counter tells how many hashes proof for each leaf has\n /// @param _leaves array of merkle leaves\n /// @return results array of verification results, TRUE if leaf is part of consensus, FALSE otherwise\n function verifyProofs(\n uint32[] memory _blockIds,\n bytes memory _proofs,\n uint256[] memory _proofItemsCounter,\n bytes32[] memory _leaves\n )\n public\n view\n returns (bool[] memory results)\n {\n results = new bool[](_leaves.length);\n uint256 offset = 0;\n\n for (uint256 i = 0; i < _leaves.length;) {\n results[i] = bytesToBytes32Array(_proofs, offset, _proofItemsCounter[i]).verify(\n roots[_blockIds[i]], _leaves[i]\n );\n\n unchecked {\n // we can uncheck because it will not overflow in a lifetime, and if someone provide invalid counter\n // we verification will not be valid (or we throw because of invalid memory access)\n offset += _proofItemsCounter[i];\n // we can uncheck because `i` will not overflow in a lifetime\n i++;\n }\n }\n }\n\n /// @param _blockId consensus ID\n /// @return root for provided consensus ID\n function getBlockRoot(uint32 _blockId) external view returns (bytes32) {\n return roots[_blockId];\n }\n\n /// @param _blockId consensus ID\n /// @return timestamp for provided consensus ID\n function getBlockTimestamp(uint32 _blockId) external view returns (uint32) {\n return roots[_blockId] == bytes32(0) ? 0 : _blockId;\n }\n\n /// @dev batch getter for FCDs\n /// @param _keys FCDs keys to fetch\n /// @return values array of FCDs values\n /// @return timestamps array of FCDs timestamps\n function getCurrentValues(bytes32[] calldata _keys)\n external\n view\n returns (uint256[] memory values, uint32[] memory timestamps)\n {\n timestamps = new uint32[](_keys.length);\n values = new uint256[](_keys.length);\n\n for (uint i=0; i<_keys.length;) {\n FirstClassData storage numericFCD = fcds[_keys[i]];\n values[i] = uint256(numericFCD.value);\n timestamps[i] = numericFCD.dataTimestamp;\n\n unchecked {\n // we can uncheck because `i` will not overflow in a lifetime\n i++;\n }\n }\n }\n\n /// @dev getter for single FCD value\n /// @param _key FCD key\n /// @return value FCD value\n /// @return timestamp FCD timestamp\n function getCurrentValue(bytes32 _key) external view returns (uint256 value, uint256 timestamp) {\n FirstClassData storage numericFCD = fcds[_key];\n return (uint256(numericFCD.value), numericFCD.dataTimestamp);\n }\n\n /// @dev getter for single FCD value in case its type is `int`\n /// @param _key FCD key\n /// @return value FCD value\n /// @return timestamp FCD timestamp\n function getCurrentIntValue(bytes32 _key) external view returns (int256 value, uint256 timestamp) {\n FirstClassData storage numericFCD = fcds[_key];\n return (numericFCD.value.toInt(), numericFCD.dataTimestamp);\n }\n\n function _setPadding(uint32 _padding) internal onlyOwner {\n if (_consensusData.padding == _padding) revert NoChangeToState();\n\n _consensusData.padding = _padding;\n emit LogPadding(msg.sender, _padding);\n }\n\n /// @dev we cloning last block time, because we will need reference point for next submissions\n function _cloneLastDataFromPrevChain(address _prevChain) internal {\n (bool success, bytes memory v) = _prevChain.staticcall(abi.encode(_VERSION_SELECTOR));\n uint256 prevVersion = success ? abi.decode(v, (uint256)) : 1;\n\n if (prevVersion == 1) {\n uint32 latestId = IBaseChainV1(address(_prevChain)).getLatestBlockId();\n _consensusData.lastTimestamp = IBaseChainV1(address(_prevChain)).getBlockTimestamp(latestId);\n\n // +1 because getLatestBlockId subtracts 1\n // +1 because it might be situation when tx is already in progress in old contract\n // and old contract do not have deprecated flag\n _consensusData.sequence = latestId + 2;\n _consensusData.blocksCountOffset = latestId + 2;\n } else { // VERSION 2\n // with new Registry, we have register/unregister methods\n // Chain will be deprecated, so there is no need to do \"+1\" as in old version\n // TODO what with current Registries??\n // we need a way to make it deprecated!\n ConsensusData memory data = BaseChain(_prevChain).getConsensusData();\n\n _consensusData.sequence = data.sequence;\n _consensusData.blocksCountOffset = data.sequence;\n _consensusData.lastTimestamp = data.lastTimestamp;\n }\n }\n}\n" + }, + "contracts/Chain.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./BaseChain.sol\";\n\ncontract Chain is BaseChain {\n IStakingBank public immutable stakingBank;\n\n event LogMint(address indexed minter, uint256 blockId, uint256 staked, uint256 power);\n event LogVoter(uint256 indexed blockId, address indexed voter, uint256 vote);\n\n error NotEnoughSignatures();\n error SignaturesOutOfOrder();\n\n /// @param _contractRegistry Registry address\n /// @param _padding required \"space\" between blocks in seconds\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n /// @param _allowForMixedType we have two \"types\" of Chain: HomeChain and ForeignChain, when we redeploying\n /// we don't want to mix up them, so we checking, if new Chain has the same type as current one.\n /// However, when we will be switching from one homechain to another one, we have to allow for this mixing up.\n /// This flag will tell contract, if this is the case.\n constructor(\n IRegistry _contractRegistry,\n uint32 _padding,\n uint16 _requiredSignatures,\n bool _allowForMixedType\n ) BaseChain(_contractRegistry, _padding, _requiredSignatures, _allowForMixedType) {\n stakingBank = IStakingBank(_contractRegistry.requireAndGetAddress(\"StakingBank\"));\n }\n\n /// @dev method for submitting consensus data\n /// @param _dataTimestamp consensus timestamp, this is time for all data in merkle tree including FCDs\n /// @param _root merkle root\n /// @param _keys FCDs keys\n /// @param _values FCDs values\n /// @param _v array of `v` part of validators signatures\n /// @param _r array of `r` part of validators signatures\n /// @param _s array of `s` part of validators signatures\n // solhint-disable-next-line function-max-lines, code-complexity\n function submit(\n uint32 _dataTimestamp,\n bytes32 _root,\n bytes32[] memory _keys,\n uint256[] memory _values,\n uint8[] memory _v,\n bytes32[] memory _r,\n bytes32[] memory _s\n ) external {\n // below two checks are only for pretty errors, so we can safe gas and allow for raw revert\n // if (_keys.length != _values.length) revert ArraysDataDoNotMatch();\n // if (_v.length != _r.length || _r.length != _s.length) revert ArraysDataDoNotMatch();\n\n _verifySubmitTimestampAndIncSequence(_dataTimestamp);\n\n // we can't expect minter will have exactly the same timestamp\n // but for sure we can demand not to be off by a lot, that's why +3sec\n // temporary remove this condition, because recently on ropsten we see cases when minter/node\n // can be even 100sec behind\n // require(_dataTimestamp <= block.timestamp + 3,\n // string(abi.encodePacked(\"oh, so you can predict the future:\", _dataTimestamp - block.timestamp + 48)));\n\n bytes memory testimony = abi.encodePacked(_dataTimestamp, _root);\n\n for (uint256 i = 0; i < _keys.length;) {\n if (uint224(_values[i]) != _values[i]) revert FCDOverflow();\n\n fcds[_keys[i]] = FirstClassData(uint224(_values[i]), _dataTimestamp);\n testimony = abi.encodePacked(testimony, _keys[i], _values[i]);\n\n unchecked {\n // we can't pass enough data to overflow\n i++;\n }\n }\n\n uint256 signatures = 0;\n uint256 power = 0;\n //uint256 staked = stakingBank.totalSupply();\n bytes32 affidavit = keccak256(testimony);\n\n address prevSigner = address(0x0);\n\n for (uint256 i; i < _v.length;) {\n address signer = recoverSigner(affidavit, _v[i], _r[i], _s[i]);\n uint256 balance = stakingBank.balanceOf(signer);\n\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\n\n prevSigner = signer;\n\n if (balance == 0) {\n unchecked { i++; }\n continue;\n }\n\n signatures++;\n emit LogVoter(uint256(_dataTimestamp), signer, balance);\n\n unchecked {\n // we can't overflow because that means token overflowed\n // and even if we do, we will get lower power\n power += balance;\n i++;\n }\n }\n\n if (signatures < _REQUIRED_SIGNATURES) revert NotEnoughSignatures();\n\n emit LogMint(msg.sender, _dataTimestamp, stakingBank.totalSupply(), power);\n\n // TODO remember to protect against flash loans when DPoS will be in place\n // we turn on power once we have DPoS in action, we have PoA now\n // require(power * 100 / staked >= 66, \"not enough power was gathered\");\n\n roots[_dataTimestamp] = _root;\n _consensusData.lastTimestamp = _dataTimestamp;\n }\n\n /// @inheritdoc BaseChain\n function isForeign() external pure virtual override returns (bool) {\n return false;\n }\n\n /// @dev helper method that returns all important data about current state of contract\n /// @return blockNumber `block.number`\n /// @return timePadding `this.padding`\n /// @return lastDataTimestamp timestamp for last submitted consensus\n /// @return lastId ID of last submitted consensus\n /// @return nextLeader leader for `block.timestamp + 1`\n /// @return nextBlockId block ID for `block.timestamp + padding`\n /// @return validators array of all validators addresses\n /// @return powers array of all validators powers\n /// @return locations array of all validators locations\n /// @return staked total UMB staked by validators\n /// @return minSignatures `this.requiredSignatures`\n function getStatus() external view virtual returns(\n uint256 blockNumber,\n uint32 timePadding,\n uint32 lastDataTimestamp,\n uint32 lastId,\n address nextLeader,\n uint32 nextBlockId,\n address[] memory validators,\n uint256[] memory powers,\n string[] memory locations,\n uint256 staked,\n uint16 minSignatures\n ) {\n ConsensusData memory data = _consensusData;\n\n blockNumber = block.number;\n timePadding = data.padding;\n lastId = data.lastTimestamp;\n lastDataTimestamp = lastId;\n minSignatures = _REQUIRED_SIGNATURES;\n\n staked = stakingBank.totalSupply();\n uint256 numberOfValidators = stakingBank.getNumberOfValidators();\n powers = new uint256[](numberOfValidators);\n validators = new address[](numberOfValidators);\n locations = new string[](numberOfValidators);\n\n for (uint256 i = 0; i < numberOfValidators;) {\n validators[i] = stakingBank.addresses(i);\n (, locations[i]) = stakingBank.validators(validators[i]);\n powers[i] = stakingBank.balanceOf(validators[i]);\n\n unchecked {\n // we will run out of gas before overflow happen\n i++;\n }\n }\n\n unchecked {\n // we will not overflow with timestamp in a lifetime\n nextBlockId = lastId + data.padding + 1;\n\n nextLeader = numberOfValidators > 0\n // we will not overflow with timestamp in a lifetime\n ? validators[getLeaderIndex(numberOfValidators, block.timestamp + 1)]\n : address(0);\n }\n }\n\n /// @return address of leader for next second\n function getNextLeaderAddress() external view returns (address) {\n return getLeaderAddressAtTime(block.timestamp + 1);\n }\n\n /// @return address of current leader\n function getLeaderAddress() external view returns (address) {\n return getLeaderAddressAtTime(block.timestamp);\n }\n\n /// @param _numberOfValidators total number of validators\n /// @param _timestamp timestamp for which you want to calculate index\n /// @return leader index, use it for StakingBank.addresses[index] to fetch leader address\n function getLeaderIndex(uint256 _numberOfValidators, uint256 _timestamp) public view virtual returns (uint256) {\n ConsensusData memory data = _consensusData;\n\n unchecked {\n // we will not overflow on `timestamp` and `padding` in a life time\n // timePadding + 1 => because padding is a space between blocks,\n // so next round starts on first block after padding\n // TODO will it work for off-chain??\n uint256 validatorIndex = data.sequence + (_timestamp - data.lastTimestamp) / (data.padding + 1);\n\n return validatorIndex % _numberOfValidators;\n }\n }\n\n // @todo - properly handled non-enabled validators, newly added validators, and validators with low stake\n /// @param _timestamp timestamp for which you want to calculate leader address\n /// @return leader address for provider timestamp\n function getLeaderAddressAtTime(uint256 _timestamp) public view virtual returns (address) {\n uint256 numberOfValidators = stakingBank.getNumberOfValidators();\n\n if (numberOfValidators == 0) {\n return address(0x0);\n }\n\n uint256 validatorIndex = getLeaderIndex(numberOfValidators, _timestamp);\n\n return stakingBank.addresses(validatorIndex);\n }\n\n /// @dev we had stack too deep in `submit` so this method was created as a solution\n // we increasing `_consensusData.sequence` here so we don't have to read sequence again in other place\n function _verifySubmitTimestampAndIncSequence(uint256 _dataTimestamp) internal {\n ConsensusData memory data = _consensusData;\n\n // `data.lastTimestamp` must be setup either on deployment\n // or via cloning from previous contract\n if (data.lastTimestamp == 0) revert ContractNotReady();\n\n unchecked {\n // we will not overflow with timestamp and padding in a life time\n if (data.lastTimestamp + data.padding >= _dataTimestamp) revert BlockSubmittedToFastOrDataToOld();\n }\n\n unchecked {\n // we will not overflow in a life time\n _consensusData.sequence = uint32(data.sequence + 1);\n }\n }\n}\n" + }, + "contracts/extensions/Registrable.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\n/// @dev Any contract that we want to register in ContractRegistry, must inherit from Registrable\nabstract contract Registrable {\n IRegistry public immutable contractRegistry;\n\n modifier onlyFromContract(address _msgSender, bytes32 _contractName) {\n require(\n contractRegistry.getAddress(_contractName) == _msgSender,\n string(abi.encodePacked(\"caller is not \", _contractName))\n );\n _;\n }\n\n modifier withRegistrySetUp() {\n require(address(contractRegistry) != address(0x0), \"_registry is empty\");\n _;\n }\n\n constructor(IRegistry _contractRegistry) {\n require(address(_contractRegistry) != address(0x0), \"_registry is empty\");\n contractRegistry = _contractRegistry;\n }\n\n /// @dev this method will be called as a first method in registration process when old contract will be replaced\n /// when called, old contract address is still in registry\n function register() virtual external;\n\n /// @dev this method will be called as a last method in registration process when old contract will be replaced\n /// when called, new contract address is already in registry\n function unregister() virtual external;\n\n /// @return contract name as bytes32\n function getName() virtual external pure returns (bytes32);\n\n /// @dev helper method for fetching StakingBank address\n function stakingBankContract() public view returns (IStakingBank) {\n return IStakingBank(contractRegistry.requireAndGetAddress(\"StakingBank\"));\n }\n\n /// @dev helper method for fetching UMB address\n function tokenContract() public view withRegistrySetUp returns (ERC20) {\n return ERC20(contractRegistry.requireAndGetAddress(\"UMB\"));\n }\n}\n" + }, + "contracts/ForeignChain.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./Chain.sol\";\n\n/// @dev contract for foreign chains\ncontract ForeignChain is Chain {\n error NotSupported();\n\n /// @param _contractRegistry Registry address\n /// @param _padding required \"space\" between blocks in seconds\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n constructor(\n IRegistry _contractRegistry,\n uint32 _padding,\n uint16 _requiredSignatures,\n bool _allowForMixedType\n ) Chain(_contractRegistry, _padding, _requiredSignatures, _allowForMixedType) {\n // no additional configuration needed\n }\n\n /// @inheritdoc BaseChain\n function isForeign() external pure override returns (bool) {\n return true;\n }\n\n /// @inheritdoc Chain\n /// @notice this method is made to be compatible with MasterChain, but it does not return full data eg validators\n /// data will be missing.\n /// @return blockNumber `block.number`\n /// @return timePadding `this.padding`\n /// @return lastDataTimestamp timestamp for last submitted consensus\n /// @return lastId ID of last submitted consensus\n /// @return nextLeader will be always address(0)\n /// @return nextBlockId block ID for `block.timestamp + padding`\n /// @return validators array will be always empty\n /// @return powers array will be always empty\n /// @return locations array will be always empty\n /// @return staked total UMB staked by validators\n /// @return minSignatures `this.requiredSignatures`\n function getStatus() external view override returns(\n uint256 blockNumber,\n uint32 timePadding,\n uint32 lastDataTimestamp,\n uint32 lastId,\n address nextLeader,\n uint32 nextBlockId,\n address[] memory validators,\n uint256[] memory powers,\n string[] memory locations,\n uint256 staked,\n uint16 minSignatures\n ) {\n ConsensusData memory data = _consensusData;\n\n blockNumber = block.number;\n timePadding = data.padding;\n lastId = data.lastTimestamp;\n lastDataTimestamp = lastId;\n minSignatures = _REQUIRED_SIGNATURES;\n\n staked = stakingBank.totalSupply();\n uint256 numberOfValidators = 0;\n powers = new uint256[](numberOfValidators);\n validators = new address[](numberOfValidators);\n locations = new string[](numberOfValidators);\n nextLeader = address(0);\n\n unchecked {\n // we will not overflow with timestamp in a lifetime\n nextBlockId = lastId + data.padding + 1;\n }\n }\n\n function getLeaderIndex(uint256, uint256) public pure override returns (uint256) {\n revert NotSupported();\n }\n\n function getLeaderAddressAtTime(uint256) public pure override returns (address) {\n revert NotSupported();\n }\n}\n" + }, + "contracts/interfaces/IBaseChainV1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IBaseChainV1 {\n /// @dev number of blocks (consensus rounds) saved in this contract\n function blocksCount() external returns (uint32);\n\n /// @dev number of all blocks that were generated before switching to this contract\n /// please note, that there might be a gap of one block when we switching from old to new contract\n /// see constructor for details\n function blocksCountOffset() external returns (uint32);\n\n function getLatestBlockId() external view returns (uint32);\n\n function getBlockTimestamp(uint32 _blockId) external view returns (uint32);\n\n function getStatus() external view returns (\n uint256 blockNumber,\n uint16 timePadding,\n uint32 lastDataTimestamp,\n uint32 lastId,\n uint32 nextBlockId\n );\n}\n" + }, + "contracts/interfaces/IRegistry.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\n\ninterface IRegistry {\n event LogRegistered(address indexed destination, bytes32 name);\n\n /// @dev imports new contract addresses and override old addresses, if they exist under provided name\n /// This method can be used for contracts that for some reason do not have `getName` method\n /// @param _names array of contract names that we want to register\n /// @param _destinations array of contract addresses\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external;\n\n /// @dev imports new contracts and override old addresses, if they exist.\n /// Names of contracts are fetched directly from each contract by calling `getName`\n /// @param _destinations array of contract addresses\n function importContracts(address[] calldata _destinations) external;\n\n /// @dev this method ensure, that old and new contract is aware of it state in registry\n /// Note: BSC registry does not have this method. This method was introduced in later stage.\n /// @param _newContract address of contract that will replace old one\n function atomicUpdate(address _newContract) external;\n\n /// @dev similar to `getAddress` but throws when contract name not exists\n /// @param name contract name\n /// @return contract address registered under provided name or throws, if does not exists\n function requireAndGetAddress(bytes32 name) external view returns (address);\n\n /// @param name contract name in a form of bytes32\n /// @return contract address registered under provided name\n function getAddress(bytes32 name) external view returns (address);\n\n /// @param _name contract name\n /// @return contract address assigned to the name or address(0) if not exists\n function getAddressByString(string memory _name) external view returns (address);\n\n /// @dev helper method that converts string to bytes32,\n /// you can use to to generate contract name\n function stringToBytes32(string memory _string) external pure returns (bytes32 result);\n}\n" + }, + "contracts/interfaces/IStakingBank.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IStakingBank is IERC20 {\n /// @param id address of validator wallet\n /// @param location URL of the validator API\n struct Validator {\n address id;\n string location;\n }\n\n event LogValidatorRegistered(address indexed id);\n event LogValidatorUpdated(address indexed id);\n event LogValidatorRemoved(address indexed id);\n event LogMinAmountForStake(uint256 minAmountForStake);\n\n /// @dev setter for `minAmountForStake`\n function setMinAmountForStake(uint256 _minAmountForStake) external;\n\n /// @dev allows to stake `token` by validators\n /// Validator needs to approve StakingBank beforehand\n /// @param _value amount of tokens to stake\n function stake(uint256 _value) external;\n\n /// @dev notification about approval from `_from` address on UMB token\n /// Staking bank will stake max approved amount from `_from` address\n /// @param _from address which approved token spend for IStakingBank\n function receiveApproval(address _from) external returns (bool success);\n\n /// @dev withdraws stake tokens\n /// it throws, when balance will be less than required minimum for stake\n /// to withdraw all use `exit`\n function withdraw(uint256 _value) external returns (bool success);\n\n /// @dev unstake and withdraw all tokens\n function exit() external returns (bool success);\n\n /// @dev creates (register) new validator\n /// @param _id validator address\n /// @param _location location URL of the validator API\n function create(address _id, string calldata _location) external;\n\n /// @dev removes validator\n /// @param _id validator wallet\n function remove(address _id) external;\n\n /// @dev updates validator location\n /// @param _id validator wallet\n /// @param _location new validator URL\n function update(address _id, string calldata _location) external;\n\n /// @return total number of registered validators (with and without balance)\n function getNumberOfValidators() external view returns (uint256);\n\n /// @dev gets validator address for provided index\n /// @param _ix index in array of list of all validators wallets\n function addresses(uint256 _ix) external view returns (address);\n\n /// @param _id address of validator\n /// @return id address of validator\n /// @return location URL of validator\n function validators(address _id) external view returns (address id, string memory location);\n}\n" + }, + "contracts/interfaces/IStakingBankStatic.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./IStakingBank.sol\";\n\n\ninterface IStakingBankStatic is IStakingBank {\n /// @param _validators array of validators addresses to verify\n /// @return TRUE when all validators are valid, FALSE otherwise\n function verifyValidators(address[] calldata _validators) external view returns (bool);\n}\n" + }, + "contracts/interfaces/IUmbrellaFeeds.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IUmbrellaFeeds {\n struct PriceData {\n /// @dev this is placeholder, that can be used for some additional data\n /// atm of creating this smart contract, it is only used as marker for removed data (when == type(uint8).max)\n uint8 data;\n /// @dev heartbeat: how often price data will be refreshed in case price stay flat\n uint24 heartbeat;\n /// @dev timestamp: price time, at this time validators run consensus\n uint32 timestamp;\n /// @dev price\n uint128 price;\n }\n\n struct Signature {\n uint8 v;\n bytes32 r;\n bytes32 s;\n }\n\n /// @dev method for submitting consensus data\n /// @param _priceKeys array of keys for `_priceDatas`\n /// @param _priceDatas PriceData signed by validators\n /// @param _signatures validators signatures\n function update(\n bytes32[] calldata _priceKeys,\n PriceData[] calldata _priceDatas,\n Signature[] calldata _signatures\n ) external;\n\n /// @dev it will return array of price datas for provided `_keys`\n /// In case ony of feed does not exist, fallback call will be executed for that feed.\n /// @notice If data for any key not exists, function will revert. Use `getManyPriceDataRaw` method if you don't\n /// want revert.\n /// @param _keys array of feed keys\n /// @return data PriceData array\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data);\n\n /// @dev same as getManyPriceData() but does not revert on empty data.\n /// @notice This method does no revert if some data does not exists.\n /// Check `data.timestamp` to see if price exist, if it is 0, then it does not exist.\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data);\n\n /// @dev this is main endpoint for reading feeds.\n /// In case timestamp is empty (that means there is no data), contract will revert.\n /// If you do not need whole data from `PriceData` struct, you can save some gas by using other view methods that\n /// returns just what you need.\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return data full PriceData struct\n function getPriceData(bytes32 _key) external view returns (PriceData memory data);\n\n /// @notice reader for mapping\n /// @param _key hash of feed name\n /// @return data full PriceData struct\n function prices(bytes32 _key) external view returns (PriceData memory data);\n\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return price\n function getPrice(bytes32 _key) external view returns (uint128 price);\n\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return price\n /// @return timestamp\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp);\n\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return price\n /// @return timestamp\n /// @return heartbeat\n function getPriceTimestampHeartbeat(bytes32 _key)\n external\n view\n returns (uint128 price, uint32 timestamp, uint24 heartbeat);\n\n /// @dev This method should be used only for Layer2 as it is more gas consuming than others views.\n /// @notice It does not revert on empty data.\n /// @param _name string feed name\n /// @return data PriceData\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data);\n\n /// @dev decimals for prices stored in this contract\n function DECIMALS() external view returns (uint8); // solhint-disable-line func-name-mixedcase\n}\n" + }, + "contracts/interfaces/StakingBankStaticNotSupported.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./IStakingBank.sol\";\n\nabstract contract StakingBankStaticNotSupported is IStakingBank {\n error NotSupported();\n\n function create(address, string calldata) external pure {\n revert NotSupported();\n }\n\n function update(address, string calldata) external pure {\n revert NotSupported();\n }\n\n function remove(address) external pure {\n revert NotSupported();\n }\n\n function transfer(address, uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function transferFrom(address, address, uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function receiveApproval(address) external pure returns (bool) {\n revert NotSupported();\n }\n\n function allowance(address, address) external pure returns (uint256) {\n revert NotSupported();\n }\n\n function approve(address, uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function stake(uint256) external pure {\n revert NotSupported();\n }\n\n function withdraw(uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function exit() external pure returns (bool) {\n revert NotSupported();\n }\n\n function setMinAmountForStake(uint256) external pure {\n revert NotSupported();\n }\n}\n" + }, + "contracts/mock/Distributor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport \"../Registry.sol\";\n\ncontract Distributor is Ownable {\n address[] public recipients;\n uint256 public bottomLimit = 5e17;\n uint256 public topLimit = 1e18;\n\n constructor(address[] memory _recipients) {\n recipients = _recipients;\n }\n\n receive() external payable {\n distribute();\n }\n\n function setLimits(uint256 _bottom, uint256 _top) external onlyOwner {\n bottomLimit = _bottom;\n topLimit = _top;\n }\n\n function withdraw() external {\n uint balance = address(this).balance;\n uint buffer = recipients.length * (topLimit - bottomLimit);\n\n if (balance > buffer) {\n payable(owner()).transfer(balance - buffer);\n }\n }\n\n function addRecipients(address[] calldata _recipients) external onlyOwner {\n for (uint256 i = 0; i < _recipients.length; i++) {\n recipients.push(_recipients[i]);\n }\n }\n\n function removeRecipient(address _recipient) external onlyOwner {\n for (uint256 i = 0; i < recipients.length; i++) {\n if (recipients[i] == _recipient) {\n recipients[i] = recipients[recipients.length - 1];\n recipients.pop();\n return;\n }\n }\n }\n\n function recipientsCount() external view returns (uint256) {\n return recipients.length;\n }\n\n function allRecipients() external view returns (address[] memory) {\n return recipients;\n }\n\n function getName() external pure returns (bytes32) {\n return \"Distributor\";\n }\n\n function distribute() public {\n uint256 limit = bottomLimit;\n uint256 top = topLimit;\n uint256 count = recipients.length;\n uint256 totalBalance = address(this).balance;\n\n for (uint256 i = 0; i < count; i++) {\n uint256 balance = recipients[i].balance;\n\n if (balance > limit) {\n continue;\n }\n\n uint256 amount = top - balance > totalBalance ? totalBalance : top - balance;\n\n if (amount > 0) {\n payable(recipients[i]).transfer(amount);\n totalBalance -= amount;\n }\n }\n }\n}\n" + }, + "contracts/mock/LimitedMintingToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\ncontract LimitedMintingToken is ERC20, Ownable {\n struct MintData {\n uint256 dailyAllowance;\n mapping (address => uint256) lastMintTimestamp;\n mapping (address => uint256) todaysMintedAmount;\n }\n\n MintData public mintData;\n\n constructor(string memory _name, string memory _symbol, uint256 _dailyAllowance) ERC20(_name, _symbol) {\n mintData.dailyAllowance = _dailyAllowance;\n }\n\n function mint(address _holder, uint256 _amount) external {\n MintData storage data = mintData;\n\n (uint256 limit, bool fullLimit) = _currentLimit(data);\n\n require(limit > 0, \"This address already claimed the maximum daily amount\");\n\n uint256 lastTimestamp = data.lastMintTimestamp[msg.sender];\n uint256 mintedAmount = data.todaysMintedAmount[msg.sender];\n\n uint256 amount = _amount > limit ? limit : _amount;\n data.lastMintTimestamp[msg.sender] = fullLimit ? block.timestamp : lastTimestamp;\n data.todaysMintedAmount[msg.sender] = fullLimit ? amount : mintedAmount + amount;\n\n _mint(_holder, amount);\n }\n\n function mintApproveAndStake(IStakingBank _stakingBank, address _holder, uint256 _amount) external {\n _mint(_holder, _amount);\n _approve(_holder, address(_stakingBank), _amount);\n _stakingBank.receiveApproval(_holder);\n }\n\n function getDailyAllowance() external view returns (uint256) {\n return mintData.dailyAllowance;\n }\n\n function getName() external pure returns (bytes32) {\n return \"UMB\";\n }\n\n function setDailyAllowance(uint256 newDailyAllowance) public onlyOwner {\n MintData storage data = mintData;\n data.dailyAllowance = newDailyAllowance;\n }\n\n function _currentLimit(MintData storage data) internal view returns (uint256 limit, bool fullLimit) {\n uint256 lastMint = data.lastMintTimestamp[msg.sender];\n fullLimit = block.timestamp - lastMint >= 24 hours;\n\n uint256 usedLimit = data.todaysMintedAmount[msg.sender];\n\n limit = fullLimit ? data.dailyAllowance : data.dailyAllowance - usedLimit;\n }\n}\n" + }, + "contracts/mock/Token.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\n// please remember this is our dummy token!\n// it will be replaced by proper DPoS solution in future\ncontract Token is ERC20 {\n constructor(\n string memory _name,\n string memory _symbol) ERC20(_name, _symbol) {\n }\n\n function mint(address _holder, uint256 _amount) external {\n _mint(_holder, _amount);\n }\n\n function mintApproveAndStake(IStakingBank _stakingBank, address _holder, uint256 _amount) external {\n _mint(_holder, _amount);\n _approve(_holder, address(_stakingBank), _amount);\n _stakingBank.receiveApproval(_holder);\n }\n\n function getName() external pure returns (bytes32) {\n return \"UMB\";\n }\n}\n" + }, + "contracts/onChainFeeds/UmbrellaFeeds.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/IUmbrellaFeeds.sol\";\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IStakingBankStatic.sol\";\n\n/// @dev Main contract for all on-chain data.\n/// Check `UmbrellaFeedsReader` to see how to integrate.\n///\n/// @notice This contract can be destroyed and replaced with new one (with new address).\n/// For best gas efficiency you should pick one of two ways of integration:\n/// 1. make `UmbrellaFeeds` immutable and use fallback in case of selfdestruct. After new deployment, it is recommended\n/// to update address to avoid fallback and reduce gas cost to minimum. In long run this is most efficient solution,\n/// better than any proxy.\n/// 2. always check newest `UmbrellaFeeds` via `Regostry` and fallback will not be needed.\ncontract UmbrellaFeeds is IUmbrellaFeeds {\n bytes constant public ETH_PREFIX = \"\\x19Ethereum Signed Message:\\n32\";\n string constant public NAME = \"UmbrellaFeeds\";\n\n /// @dev deployment time, used for protect for unintentional destroy\n uint256 public immutable DEPLOYED_AT; // solhint-disable-line var-name-mixedcase\n\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\n /// resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev StakingBank contract where list of validators is stored\n IStakingBankStatic public immutable STAKING_BANK; // solhint-disable-line var-name-mixedcase\n\n /// @dev minimal number of signatures required for accepting price submission (PoA)\n uint16 public immutable REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\n\n /// @dev decimals for prices stored in this contract\n uint8 public immutable DECIMALS; // solhint-disable-line var-name-mixedcase\n\n /// @notice map of all prices stored in this contract, key for map is hash of feed name\n /// eg for \"ETH-USD\" feed, key will be hash(\"ETH-USD\")\n mapping (bytes32 => PriceData) private _prices;\n\n error ArraysDataDoNotMatch();\n error FeedNotExist();\n error NotEnoughSignatures();\n error InvalidSigner();\n error InvalidRequiredSignatures();\n error SignaturesOutOfOrder();\n error ECDSAInvalidSignatureS();\n error ECDSAInvalidSignatureV();\n error OldData();\n error ContractInUse();\n error ContractNotInitialised();\n\n /// @param _contractRegistry Registry address\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n /// @param _decimals decimals for prices stored in this contract\n constructor(\n IRegistry _contractRegistry,\n uint16 _requiredSignatures,\n uint8 _decimals\n ) {\n if (_requiredSignatures == 0) revert InvalidRequiredSignatures();\n\n REGISTRY = _contractRegistry;\n REQUIRED_SIGNATURES = _requiredSignatures;\n STAKING_BANK = IStakingBankStatic(_contractRegistry.requireAndGetAddress(\"StakingBank\"));\n DECIMALS = _decimals;\n DEPLOYED_AT = block.timestamp;\n }\n\n /// @dev destroys old contract\n /// there is sanity check that prevents abuse of destroy method\n /// @param _name string feed key to verify, that contract was initialised\n function destroy(string calldata _name) external {\n if (REGISTRY.getAddressByString(NAME) == address(this)) revert ContractInUse();\n\n if (_prices[keccak256(abi.encodePacked(_name))].timestamp == 0 && DEPLOYED_AT + 3 days > block.timestamp) {\n revert ContractNotInitialised();\n }\n\n selfdestruct(payable(msg.sender));\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function update(\n bytes32[] calldata _priceKeys,\n PriceData[] calldata _priceDatas,\n Signature[] calldata _signatures\n ) external {\n if (_priceKeys.length != _priceDatas.length) revert ArraysDataDoNotMatch();\n\n bytes32 priceDataHash = keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n verifySignatures(priceDataHash, _signatures);\n\n uint256 i;\n\n while (i < _priceDatas.length) {\n bytes32 priceKey = _priceKeys[i];\n\n // we do not allow for older prices\n // at the same time it prevents from reusing signatures\n if (_prices[priceKey].timestamp >= _priceDatas[i].timestamp) revert OldData();\n\n _prices[priceKey] = _priceDatas[i];\n\n // atm there is no need for events, so in order to save gas, we do not emit any\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n if (data[i].timestamp == 0) revert FeedNotExist();\n\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function prices(bytes32 _key) external view returns (PriceData memory data) {\n data = _prices[_key];\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceData(bytes32 _key) external view returns (PriceData memory data) {\n data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPrice(bytes32 _key) external view returns (uint128 price) {\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return data.price;\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp) {\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp);\n }\n\n function getPriceTimestampHeartbeat(bytes32 _key)\n external\n view\n returns (uint128 price, uint32 timestamp, uint24 heartbeat)\n {\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp, data.heartbeat);\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data) {\n bytes32 key = keccak256(abi.encodePacked(_name));\n data = _prices[key];\n }\n\n /// @dev helper method for QA purposes\n /// @return hash of data that are signed by validators (keys and priced data)\n function hashData(bytes32[] calldata _priceKeys, PriceData[] calldata _priceDatas)\n external\n view\n returns (bytes32)\n {\n return keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n }\n\n /// @param _hash hash of signed data\n /// @param _signatures array of validators signatures\n function verifySignatures(bytes32 _hash, Signature[] calldata _signatures) public view {\n address prevSigner = address(0x0);\n\n if (_signatures.length < REQUIRED_SIGNATURES) revert NotEnoughSignatures();\n\n address[] memory validators = new address[](REQUIRED_SIGNATURES);\n\n // to save gas we check only required number of signatures\n // case, where you can have part of signatures invalid but still enough valid in total is not supported\n for (uint256 i; i < REQUIRED_SIGNATURES;) {\n (uint8 v, bytes32 r, bytes32 s) = (_signatures[i].v, _signatures[i].r, _signatures[i].s);\n\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n revert ECDSAInvalidSignatureS();\n }\n\n if (uint8(v) != 27 && uint8(v) != 28) revert ECDSAInvalidSignatureV();\n\n address signer = recoverSigner(_hash, v, r, s);\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\n\n // because we check only required number of signatures, any invalid one will cause revert\n prevSigner = signer;\n validators[i] = signer;\n\n unchecked { i++; }\n }\n\n // bulk verification can optimise gas when we have 5 or more validators\n if (!STAKING_BANK.verifyValidators(validators)) revert InvalidSigner();\n }\n\n function getChainId() public view returns (uint256 id) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n id := chainid()\n }\n }\n\n /// @param _hash hashed of data\n /// @param _v part of signature\n /// @param _r part of signature\n /// @param _s part of signature\n /// @return signer address\n function recoverSigner(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _hash));\n return ecrecover(hash, _v, _r, _s);\n }\n\n /// @dev to follow Registrable interface\n function getName() public pure returns (bytes32) {\n return \"UmbrellaFeeds\";\n }\n}\n" + }, + "contracts/onChainFeeds/UmbrellaFeedsReader.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IUmbrellaFeeds.sol\";\n\n/// @dev This is optional price reader for just one feed.\n/// It comes with chanilink interface that makes migration process easier.\n/// For maximum gas optimisation it is recommended to use UmbrellaFeeds directly - simply follow this contract as\n/// a guide for integration.\n///\n/// This contract has build in fallback feature in case, `UmbrellaFeeds` will be replaced by newer contract.\n/// Fallback is transparent for the user, no additional setup is needed.\n///\n/// How fallback feature works? If data for provided key is empty (when UmbrellaFeeds was destroyed and replaced),\n/// contract will execute following procedure:\n/// 1. if data is empty, contract will check if there is new registered contract with requested data\n/// 2. if data is found in new contract it will be returned\n/// 3. if there is no data or there is no new contract tx will revert.\ncontract UmbrellaFeedsReader {\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\n /// resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev contract where all the feeds are stored\n address public immutable UMBRELLA_FEEDS; // solhint-disable-line var-name-mixedcase\n\n /// @dev key (hash of string key), under which feed is being stored\n bytes32 public immutable KEY; // solhint-disable-line var-name-mixedcase\n\n /// @dev string representation of feed key (feed name)\n string public description;\n\n /// @dev decimals for feed\n uint8 internal immutable _DECIMALS; // solhint-disable-line var-name-mixedcase\n\n error EmptyAddress();\n error FeedNotExist();\n\n /// @param _registry IRegistry address\n /// @param _umbrellaFeeds UmbrellaFeeds address\n /// @param _key price data key (before hashing)\n constructor(IRegistry _registry, IUmbrellaFeeds _umbrellaFeeds, string memory _key) {\n if (address(_registry) == address(0)) revert EmptyAddress();\n\n REGISTRY = _registry;\n UMBRELLA_FEEDS = address(_umbrellaFeeds);\n description = _key;\n _DECIMALS = _umbrellaFeeds.DECIMALS();\n\n bytes32 hash = keccak256(abi.encodePacked(_key));\n KEY = hash;\n\n // sanity check\n _umbrellaFeeds.getPriceData(hash);\n }\n\n /// @dev decimals for feed\n function decimals() external view returns (uint8) {\n return _DECIMALS;\n }\n\n /// @dev this method follows chainlink interface for easy migration, NOTE: not all returned data are covered!\n /// latestRoundData() raise exception when there is no data, instead of returning unset values,\n /// which could be misinterpreted as actual reported values.\n /// It DOES NOT raise when data is outdated (based on heartbeat and timestamp).\n /// @notice You can save some gas by doing call directly to `UMBRELLA_FEEDS` contract.\n /// @return uint80 originally `roundId`, not in use, always 0\n /// @return answer price\n /// @return uint256 originally `startedAt`, not in use, always 0\n /// @return updatedAt last timestamp data was updated\n /// @return uint80 originally `answeredInRound` not in use, always 0\n function latestRoundData()\n external\n view\n returns (\n uint80 /* roundId */,\n int256 answer,\n uint256 /* startedAt */,\n uint256 updatedAt,\n uint80 /* answeredInRound */\n )\n {\n IUmbrellaFeeds.PriceData memory priceData = _getPriceDataRaw();\n\n if (priceData.timestamp == 0) {\n priceData = _fallbackCall();\n }\n\n return (0, int256(uint256(priceData.price)), 0, priceData.timestamp, 0);\n }\n\n /// @dev this is main endpoint for reading feed. Feed is read from UmbrellaFeeds contract using hardcoded `KEY`.\n /// In case timestamp is empty (that means there is no data), contract will execute fallback call.\n /// @notice revert on empty data\n function getPriceData() external view returns (IUmbrellaFeeds.PriceData memory priceData) {\n priceData = _getPriceDataRaw();\n\n if (priceData.timestamp == 0) {\n priceData = _fallbackCall();\n }\n }\n\n /// @dev same as `getPriceData` but does not revert when no data\n function getPriceDataRaw() external view returns (IUmbrellaFeeds.PriceData memory priceData) {\n priceData = _getPriceDataRaw();\n\n if (priceData.timestamp == 0) {\n return _fallbackCallRaw();\n }\n }\n\n /// @dev same as `getPriceData` but does not revert when no data\n function _getPriceDataRaw() internal view returns (IUmbrellaFeeds.PriceData memory priceData) {\n (bool success, bytes memory data) = UMBRELLA_FEEDS.staticcall(\n abi.encodeWithSelector(IUmbrellaFeeds.prices.selector, KEY)\n );\n\n if (success && data.length != 0) {\n priceData = abi.decode(data, (IUmbrellaFeeds.PriceData));\n }\n }\n\n /// @dev it will revert on empty data\n function _fallbackCall() internal view returns (IUmbrellaFeeds.PriceData memory data) {\n address umbrellaFeeds = REGISTRY.getAddressByString(\"UmbrellaFeeds\");\n\n // if contract was NOT updated, fallback is not needed, data does not exist - revert\n if (umbrellaFeeds == UMBRELLA_FEEDS) revert FeedNotExist();\n\n data = IUmbrellaFeeds(umbrellaFeeds).getPriceData(KEY);\n }\n\n /// @dev it will not revert on empty data\n function _fallbackCallRaw() internal view returns (IUmbrellaFeeds.PriceData memory data) {\n address umbrellaFeeds = REGISTRY.getAddressByString(\"UmbrellaFeeds\");\n\n // if contract was updated, we do fallback\n if (umbrellaFeeds != UMBRELLA_FEEDS) {\n data = IUmbrellaFeeds(umbrellaFeeds).prices(KEY);\n }\n }\n}\n" + }, + "contracts/onChainFeeds/UmbrellaFeedsReaderFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\nimport \"./UmbrellaFeedsReader.sol\";\n\n/// @notice Factory to deploy UmbrellaFeedsReader contract\ncontract UmbrellaFeedsReaderFactory {\n /// @dev Registry contract where list of all addresses is stored. Used to resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev list of all readers\n mapping (bytes32 => UmbrellaFeedsReader) public readers;\n\n event NewUmbrellaFeedsReader(UmbrellaFeedsReader indexed umbrellaFeedsReader, string feedName);\n\n error EmptyAddress();\n\n constructor(IRegistry _registry) {\n if (address(_registry) == address(0)) revert EmptyAddress();\n\n REGISTRY = _registry;\n }\n\n /// @dev Method to deploy new UmbrellaFeedsReader for particular key.\n /// This deployment is optional and it can be done by anyone who needs it.\n /// Reader can be used to simplify migration from Chainlink to Umbrella.\n ///\n /// Check UmbrellaFeedsReader docs for more details.\n ///\n /// We not using minimal proxy because it does not allow for immutable variables.\n /// @param _feedName string Feed name that is registered in UmbrellaFeeds\n /// @return reader UmbrellaFeedsReader contract address, in case anyone wants to use it from Layer1\n function deploy(string memory _feedName) external returns (UmbrellaFeedsReader reader) {\n reader = deployed(_feedName);\n IUmbrellaFeeds umbrellaFeeds = IUmbrellaFeeds(REGISTRY.getAddressByString(\"UmbrellaFeeds\"));\n\n // if UmbrellaFeeds contract is up to date, there is no need to redeploy\n if (address(reader) != address(0) && address(reader.UMBRELLA_FEEDS()) == address(umbrellaFeeds)) {\n return reader;\n }\n\n reader = new UmbrellaFeedsReader(REGISTRY, umbrellaFeeds, _feedName);\n readers[hash(_feedName)] = reader;\n\n emit NewUmbrellaFeedsReader(reader, _feedName);\n }\n\n function deployed(string memory _feedName) public view returns (UmbrellaFeedsReader) {\n return readers[hash(_feedName)];\n }\n\n function hash(string memory _feedName) public pure returns (bytes32) {\n return keccak256(abi.encodePacked(_feedName));\n }\n\n /// @dev to follow Registrable interface\n function getName() public pure returns (bytes32) {\n return \"UmbrellaFeedsReaderFactory\";\n }\n}\n" + }, + "contracts/onChainFeeds/zk-link/UmbrellaFeeds.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../../interfaces/IUmbrellaFeeds.sol\";\nimport \"../../interfaces/IRegistry.sol\";\nimport \"../../interfaces/IStakingBankStatic.sol\";\n\n/// @dev Main contract for all on-chain data.\n/// Check `UmbrellaFeedsReader` to see how to integrate.\n///\n/// @notice This contract can be destroyed and replaced with new one (with new address).\n/// For best gas efficiency you should pick one of two ways of integration:\n/// 1. make `UmbrellaFeeds` immutable and use fallback in case of selfdestruct. After new deployment, it is recommended\n/// to update address to avoid fallback and reduce gas cost to minimum. In long run this is most efficient solution,\n/// better than any proxy.\n/// 2. always check newest `UmbrellaFeeds` via `Regostry` and fallback will not be needed.\ncontract UmbrellaFeeds is IUmbrellaFeeds {\n bytes constant public ETH_PREFIX = \"\\x19Ethereum Signed Message:\\n32\";\n string constant public NAME = \"UmbrellaFeeds\";\n\n /// @dev deployment time, used for protect for unintentional destroy\n uint256 public immutable DEPLOYED_AT; // solhint-disable-line var-name-mixedcase\n\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\n /// resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev StakingBank contract where list of validators is stored\n IStakingBankStatic public immutable STAKING_BANK; // solhint-disable-line var-name-mixedcase\n\n /// @dev minimal number of signatures required for accepting price submission (PoA)\n uint16 public immutable REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\n\n /// @dev decimals for prices stored in this contract\n uint8 public immutable DECIMALS; // solhint-disable-line var-name-mixedcase\n\n /// @dev in case selfdestruct is not supported, this flag will make sure contract is not usable anymore\n bool public disabled;\n\n /// @notice map of all prices stored in this contract, key for map is hash of feed name\n /// eg for \"ETH-USD\" feed, key will be hash(\"ETH-USD\")\n mapping (bytes32 => PriceData) private _prices;\n\n error SelfDestruct();\n error ArraysDataDoNotMatch();\n error FeedNotExist();\n error NotEnoughSignatures();\n error InvalidSigner();\n error InvalidRequiredSignatures();\n error SignaturesOutOfOrder();\n error ECDSAInvalidSignatureS();\n error ECDSAInvalidSignatureV();\n error OldData();\n error ContractInUse();\n error ContractNotInitialised();\n\n /// @param _contractRegistry Registry address\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n /// @param _decimals decimals for prices stored in this contract\n constructor(\n IRegistry _contractRegistry,\n uint16 _requiredSignatures,\n uint8 _decimals\n ) {\n if (_requiredSignatures == 0) revert InvalidRequiredSignatures();\n\n REGISTRY = _contractRegistry;\n REQUIRED_SIGNATURES = _requiredSignatures;\n STAKING_BANK = IStakingBankStatic(_contractRegistry.requireAndGetAddress(\"StakingBank\"));\n DECIMALS = _decimals;\n DEPLOYED_AT = block.timestamp;\n }\n\n /// @dev destroys old contract\n /// there is sanity check that prevents abuse of destroy method\n /// @param _name string feed key to verify, that contract was initialised\n function destroy(string calldata _name) external {\n if (REGISTRY.getAddressByString(NAME) == address(this)) revert ContractInUse();\n\n if (_prices[keccak256(abi.encodePacked(_name))].timestamp == 0 && DEPLOYED_AT + 3 days > block.timestamp) {\n revert ContractNotInitialised();\n }\n\n disabled = true;\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function update(\n bytes32[] calldata _priceKeys,\n PriceData[] calldata _priceDatas,\n Signature[] calldata _signatures\n ) external {\n if (disabled) revert SelfDestruct();\n if (_priceKeys.length != _priceDatas.length) revert ArraysDataDoNotMatch();\n\n bytes32 priceDataHash = keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n verifySignatures(priceDataHash, _signatures);\n\n uint256 i;\n\n while (i < _priceDatas.length) {\n bytes32 priceKey = _priceKeys[i];\n\n // we do not allow for older prices\n // at the same time it prevents from reusing signatures\n if (_prices[priceKey].timestamp >= _priceDatas[i].timestamp) revert OldData();\n\n _prices[priceKey] = _priceDatas[i];\n\n // atm there is no need for events, so in order to save gas, we do not emit any\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n if (disabled) revert SelfDestruct();\n\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n if (data[i].timestamp == 0) revert FeedNotExist();\n\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n if (disabled) revert SelfDestruct();\n\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function prices(bytes32 _key) external view returns (PriceData memory data) {\n if (disabled) revert SelfDestruct();\n\n data = _prices[_key];\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceData(bytes32 _key) external view returns (PriceData memory data) {\n if (disabled) revert SelfDestruct();\n\n data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPrice(bytes32 _key) external view returns (uint128 price) {\n if (disabled) revert SelfDestruct();\n\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return data.price;\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp) {\n if (disabled) revert SelfDestruct();\n\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp);\n }\n\n function getPriceTimestampHeartbeat(bytes32 _key)\n external\n view\n returns (uint128 price, uint32 timestamp, uint24 heartbeat)\n {\n if (disabled) revert SelfDestruct();\n\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp, data.heartbeat);\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data) {\n if (disabled) revert SelfDestruct();\n\n bytes32 key = keccak256(abi.encodePacked(_name));\n data = _prices[key];\n }\n\n /// @dev helper method for QA purposes\n /// @return hash of data that are signed by validators (keys and priced data)\n function hashData(bytes32[] calldata _priceKeys, PriceData[] calldata _priceDatas)\n external\n view\n returns (bytes32)\n {\n return keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n }\n\n /// @param _hash hash of signed data\n /// @param _signatures array of validators signatures\n function verifySignatures(bytes32 _hash, Signature[] calldata _signatures) public view {\n address prevSigner = address(0x0);\n\n if (_signatures.length < REQUIRED_SIGNATURES) revert NotEnoughSignatures();\n\n address[] memory validators = new address[](REQUIRED_SIGNATURES);\n\n // to save gas we check only required number of signatures\n // case, where you can have part of signatures invalid but still enough valid in total is not supported\n for (uint256 i; i < REQUIRED_SIGNATURES;) {\n (uint8 v, bytes32 r, bytes32 s) = (_signatures[i].v, _signatures[i].r, _signatures[i].s);\n\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n revert ECDSAInvalidSignatureS();\n }\n\n if (uint8(v) != 27 && uint8(v) != 28) revert ECDSAInvalidSignatureV();\n\n address signer = recoverSigner(_hash, v, r, s);\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\n\n // because we check only required number of signatures, any invalid one will cause revert\n prevSigner = signer;\n validators[i] = signer;\n\n unchecked { i++; }\n }\n\n // bulk verification can optimise gas when we have 5 or more validators\n if (!STAKING_BANK.verifyValidators(validators)) revert InvalidSigner();\n }\n\n function getChainId() public view returns (uint256 id) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n id := chainid()\n }\n }\n\n /// @param _hash hashed of data\n /// @param _v part of signature\n /// @param _r part of signature\n /// @param _s part of signature\n /// @return signer address\n function recoverSigner(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _hash));\n return ecrecover(hash, _v, _r, _s);\n }\n\n /// @dev to follow Registrable interface\n function getName() public pure returns (bytes32) {\n return \"UmbrellaFeeds\";\n }\n}\n" + }, + "contracts/Registry.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\n// Inheritance\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport \"./extensions/Registrable.sol\";\nimport \"./interfaces/IRegistry.sol\";\n\n/// @dev contracts registry\n/// protocol uses this registry to fetch current contract addresses\ncontract Registry is IRegistry, Ownable {\n /// name => contract address\n mapping(bytes32 => address) public registry;\n\n\n error NameNotRegistered();\n error ArraysDataDoNotMatch();\n\n /// @inheritdoc IRegistry\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external onlyOwner {\n if (_names.length != _destinations.length) revert ArraysDataDoNotMatch();\n\n for (uint i = 0; i < _names.length;) {\n registry[_names[i]] = _destinations[i];\n emit LogRegistered(_destinations[i], _names[i]);\n\n unchecked {\n i++;\n }\n }\n }\n\n /// @inheritdoc IRegistry\n function importContracts(address[] calldata _destinations) external onlyOwner {\n for (uint i = 0; i < _destinations.length;) {\n bytes32 name = Registrable(_destinations[i]).getName();\n registry[name] = _destinations[i];\n emit LogRegistered(_destinations[i], name);\n\n unchecked {\n i++;\n }\n }\n }\n\n /// @inheritdoc IRegistry\n function atomicUpdate(address _newContract) external onlyOwner {\n Registrable(_newContract).register();\n\n bytes32 name = Registrable(_newContract).getName();\n address oldContract = registry[name];\n registry[name] = _newContract;\n\n Registrable(oldContract).unregister();\n\n emit LogRegistered(_newContract, name);\n }\n\n /// @inheritdoc IRegistry\n function requireAndGetAddress(bytes32 name) external view returns (address) {\n address _foundAddress = registry[name];\n if (_foundAddress == address(0)) revert NameNotRegistered();\n\n return _foundAddress;\n }\n\n /// @inheritdoc IRegistry\n function getAddress(bytes32 _bytes) external view returns (address) {\n return registry[_bytes];\n }\n\n /// @inheritdoc IRegistry\n function getAddressByString(string memory _name) public view returns (address) {\n return registry[stringToBytes32(_name)];\n }\n\n /// @inheritdoc IRegistry\n function stringToBytes32(string memory _string) public pure returns (bytes32 result) {\n bytes memory tempEmptyStringTest = bytes(_string);\n\n if (tempEmptyStringTest.length == 0) {\n return 0x0;\n }\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n result := mload(add(_string, 32))\n }\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStatic.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/StakingBankStaticNotSupported.sol\";\n\n/// @dev Because we are using PoA in UMB oracle, staked balance does not matter. What's matter is, if signer is\n/// validator or not. In this case we can optimise `StakingBank` and make it static for better gas performance.\nabstract contract StakingBankStatic is StakingBankStaticNotSupported {\n uint256 public constant ONE = 1e18;\n\n uint256 public immutable NUMBER_OF_VALIDATORS; // solhint-disable-line var-name-mixedcase\n uint256 public immutable TOTAL_SUPPLY; // solhint-disable-line var-name-mixedcase\n\n constructor(uint256 _validatorsCount) {\n NUMBER_OF_VALIDATORS = _validatorsCount;\n TOTAL_SUPPLY = _validatorsCount * ONE;\n\n _assertValidSetup(_validatorsCount);\n }\n\n function balances(address _validator) external view returns (uint256) {\n return _isValidator(_validator) ? ONE : 0;\n }\n\n function verifyValidators(address[] calldata _validators) external view returns (bool) {\n for (uint256 i; i < _validators.length;) {\n if (!_isValidator(_validators[i])) return false;\n unchecked { i++; }\n }\n\n return true;\n }\n\n function getNumberOfValidators() external view returns (uint256) {\n return NUMBER_OF_VALIDATORS;\n }\n\n function getAddresses() external view returns (address[] memory) {\n return _addresses();\n }\n\n function getBalances() external view returns (uint256[] memory allBalances) {\n allBalances = new uint256[](NUMBER_OF_VALIDATORS);\n\n for (uint256 i; i < NUMBER_OF_VALIDATORS;) {\n allBalances[i] = ONE;\n\n unchecked {\n // we will not have enough data to overflow\n i++;\n }\n }\n }\n\n function addresses(uint256 _ix) external view returns (address) {\n return _addresses()[_ix];\n }\n\n function validators(address _id) external view virtual returns (address id, string memory location);\n\n /// @dev to follow ERC20 interface\n function balanceOf(address _account) external view returns (uint256) {\n return _isValidator(_account) ? ONE : 0;\n }\n\n /// @dev to follow ERC20 interface\n function totalSupply() external view returns (uint256) {\n return TOTAL_SUPPLY;\n }\n\n /// @dev to follow Registrable interface\n function getName() external pure returns (bytes32) {\n return \"StakingBank\";\n }\n\n /// @dev to follow Registrable interface\n function register() external pure {\n // there are no requirements atm\n }\n\n /// @dev to follow Registrable interface\n function unregister() external pure {\n // there are no requirements atm\n }\n\n function _addresses() internal view virtual returns (address[] memory);\n\n function _isValidator(address _validator) internal view virtual returns (bool);\n\n function _assertValidSetup(uint256 _validatorsCount) internal view virtual{\n address[] memory list = _addresses();\n require(list.length == _validatorsCount);\n\n for (uint256 i; i < _validatorsCount;) {\n require(_isValidator(list[i]));\n\n unchecked { i ++; }\n }\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticCI.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticCI is StakingBankStatic {\n // 0x87630b2d1de0fbd5044eb6891b3d9d98c34c8d310c852f98550ba774480e47cc\n address public constant VALIDATOR_0 = 0x2fFd013AaA7B5a7DA93336C2251075202b33FB2B;\n // 0x3f1e8b94c70206bf816c1ed0b15ad98bdf225ae4c6e7e4eee6cdbcf706fda2ae\n address public constant VALIDATOR_1 = 0x43158ea338Ff13D0bDa0c3EB969B9EA5a624E7Cc;\n // 0x5da6b84117504d06b5dcd52b990d76965d2882f4e5852eb610bc76e4209b10d7\n address public constant VALIDATOR_2 = 0x9Fd8DD0627b9A32399Fd115c4725C7e17BC40e6d;\n // 0x1e5012671de3332ad0b43661984e94ab0e405bffddc9d3e863055040bab354b8\n address public constant VALIDATOR_3 = 0xa3F3659E469b7aE0b249546338DEdc0b684edB05;\n // 0x0edc1e35ea7701ddac703286674e79f04addbf5d2f6162fabc19d39bd3dc6662\n address public constant VALIDATOR_4 = 0xB98A954B9036DF144d685E910bfbAEC6B33A8d11;\n // 0x23c601ae397441f3ef6f1075dcb0031ff17fb079837beadaf3c84d96c6f3e569\n address public constant VALIDATOR_5 = 0xE5904695748fe4A84b40b3fc79De2277660BD1D3;\n\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.ci.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.ci.umb.network\");\n if (_id == VALIDATOR_2) return (_id, \"https://validator3.ci.umb.network\");\n if (_id == VALIDATOR_3) return (_id, \"https://validator4.ci.umb.network\");\n if (_id == VALIDATOR_4) return (_id, \"https://validator5.ci.umb.network\");\n if (_id == VALIDATOR_5) return (_id, \"https://validator6.ci.umb.network\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n list[2] = VALIDATOR_2;\n list[3] = VALIDATOR_3;\n list[4] = VALIDATOR_4;\n list[5] = VALIDATOR_5;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0\n || _validator == VALIDATOR_1\n || _validator == VALIDATOR_2\n || _validator == VALIDATOR_3\n || _validator == VALIDATOR_4\n || _validator == VALIDATOR_5\n );\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticDev.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticDev is StakingBankStatic {\n address public constant VALIDATOR_0 = 0xDc3eBc37DA53A644D67E5E3b5BA4EEF88D969d5C;\n address public constant VALIDATOR_1 = 0x998cb7821e605cC16b6174e7C50E19ADb2Dd2fB0;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.dev.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.dev.umb.network\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0 || _validator == VALIDATOR_1);\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticLocal.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticLocal is StakingBankStatic {\n address public constant VALIDATOR_0 = 0xeAD9C93b79Ae7C1591b1FB5323BD777E86e150d4;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"localhost\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0);\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticProd.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\ncontract StakingBankStaticProd is StakingBankStatic {\n address public constant VALIDATOR_0 = 0x977Ba523420110e230643B772Fe9cF955e11dA7B;\n address public constant VALIDATOR_1 = 0xe2422b23e52bc13ebA04d7FbB9F332Deb43360fB;\n\n // external order is based on validators submits on AVAX for Apr 2023\n address public constant VALIDATOR_2 = 0x57F404aD75e371c1A539589C1eFCA12e0C6980AD;\n address public constant VALIDATOR_3 = 0xD56C6A4f64E0bD70260472d1DB6Cf5825858CB0d;\n address public constant VALIDATOR_4 = 0x93FdcAB283b0BcAc48157590af482E1CFd6af6aC;\n address public constant VALIDATOR_5 = 0xCd733E06B06083d52fC5867E8E3432aA5c103A38;\n address public constant VALIDATOR_6 = 0x42e210b110c6aa49CdfA7ceF1444Aa4719653111;\n address public constant VALIDATOR_7 = 0x501731c6a69803a53Ec6c3e12f293c247cE1092B;\n address public constant VALIDATOR_8 = 0x8bF9661F1b247522C75DD0FE84355aD2EfF27144;\n address public constant VALIDATOR_9 = 0x281754Ab58391A478B7aA4E7f39991CfB41118c4;\n address public constant VALIDATOR_10 = 0x57A51D5BDcE188c2295fCA3b4687475a54E65A02;\n address public constant VALIDATOR_11 = 0x2F85824B2B38F179E451988670935d315b5b9692;\n address public constant VALIDATOR_12 = 0xA7241994267682de4dE7Ef62f52dc2C783d1784B;\n address public constant VALIDATOR_13 = 0x6eEd457C20603EDAE50C3A112CAA1a9425321bD0;\n address public constant VALIDATOR_14 = 0xC5a7650c2725a7B6A39f15cb9FbffC7af357AFeb;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n // solhint-disable-next-line code-complexity\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.umb.network\");\n if (_id == VALIDATOR_2) return (_id, \"https://umbrella.artemahr.tech\");\n if (_id == VALIDATOR_3) return (_id, \"https://umb.vtabsolutions.com:3030\");\n if (_id == VALIDATOR_4) return (_id, \"https://umbrella.crazywhale.es\");\n if (_id == VALIDATOR_5) return (_id, \"https://umbrella-node.gateomega.com\");\n if (_id == VALIDATOR_6) return (_id, \"https://umb.anorak.technology\");\n if (_id == VALIDATOR_7) return (_id, \"https://umbrella.validator.infstones.io\");\n if (_id == VALIDATOR_8) return (_id, \"https://umb.hashkey.cloud\");\n if (_id == VALIDATOR_9) return (_id, \"http://umbrella.staking4all.org:3000\");\n if (_id == VALIDATOR_10) return (_id, \"http://5.161.78.230:3000\");\n if (_id == VALIDATOR_11) return (_id, \"https://umb-api.staking.rocks\");\n if (_id == VALIDATOR_12) return (_id, \"https://rpc.urbanhq.net\");\n if (_id == VALIDATOR_13) return (_id, \"https://umbrella-node.ankastake.com\");\n if (_id == VALIDATOR_14) return (_id, \"https://umbrella.tchambrella.com\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n list[2] = VALIDATOR_2;\n list[3] = VALIDATOR_3;\n list[4] = VALIDATOR_4;\n list[5] = VALIDATOR_5;\n list[6] = VALIDATOR_6;\n list[7] = VALIDATOR_7;\n list[8] = VALIDATOR_8;\n list[9] = VALIDATOR_9;\n list[10] = VALIDATOR_10;\n list[11] = VALIDATOR_11;\n list[12] = VALIDATOR_12;\n list[13] = VALIDATOR_13;\n list[14] = VALIDATOR_14;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (\n _validator == VALIDATOR_0\n || _validator == VALIDATOR_1\n || _validator == VALIDATOR_2\n || _validator == VALIDATOR_3\n || _validator == VALIDATOR_4\n || _validator == VALIDATOR_5\n || _validator == VALIDATOR_6\n || _validator == VALIDATOR_7\n || _validator == VALIDATOR_8\n || _validator == VALIDATOR_9\n || _validator == VALIDATOR_10\n || _validator == VALIDATOR_11\n || _validator == VALIDATOR_12\n || _validator == VALIDATOR_13\n || _validator == VALIDATOR_14\n );\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticSbx.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticSbx is StakingBankStatic {\n address public constant VALIDATOR_0 = 0xE3bDa0C6E1fBB111091Dfef6f22a673b20Ea5F50;\n address public constant VALIDATOR_1 = 0xc1773490F00963CBAb3841fc07C1a0796E658Ba2;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.sbx.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.sbx.umb.network\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0 || _validator == VALIDATOR_1);\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": false, + "runs": 0 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/base_production/StakingBankStatic.json b/deployments/base_production/StakingBankStatic.json index 3538d568..181f9a5d 100644 --- a/deployments/base_production/StakingBankStatic.json +++ b/deployments/base_production/StakingBankStatic.json @@ -1,5 +1,5 @@ { - "address": "0xEbcf96317D526b82B5f4cA2efde6d5C57eA2f9c7", + "address": "0xeEb5b6171f05e7313b02df59bee7214254C36317", "abi": [ { "inputs": [ @@ -249,58 +249,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "VALIDATOR_15", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATOR_16", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATOR_17", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATOR_18", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "VALIDATOR_2", @@ -812,30 +760,30 @@ "type": "function" } ], - "transactionHash": "0x39a801c6f40e66f476eb3bba8e228c83b5df08b4b33490ce057e601045a85128", + "transactionHash": "0x3193d423e5068c43a98e06675a9894ec2a0ec2fdb6bec3d6675d17178e7e3224", "receipt": { "to": null, "from": "0xA6e4fFa19B213AbeA258ae72e8e1a209B9E543e7", - "contractAddress": "0xEbcf96317D526b82B5f4cA2efde6d5C57eA2f9c7", - "transactionIndex": 4, - "gasUsed": "2643132", + "contractAddress": "0xeEb5b6171f05e7313b02df59bee7214254C36317", + "transactionIndex": 82, + "gasUsed": "2301671", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x7111118295863a0e82b237362922039789774510b16921d3809c9a23bacf44d8", - "transactionHash": "0x39a801c6f40e66f476eb3bba8e228c83b5df08b4b33490ce057e601045a85128", + "blockHash": "0x526b7f96fe27bb175228cb2569fa53f673d19be70e40699ad8df51e19b1fbf94", + "transactionHash": "0x3193d423e5068c43a98e06675a9894ec2a0ec2fdb6bec3d6675d17178e7e3224", "logs": [], - "blockNumber": 6281343, - "cumulativeGasUsed": "2976249", + "blockNumber": 21748301, + "cumulativeGasUsed": "14875590", "status": 1, "byzantium": true }, "args": [ - 19 + 15 ], - "numDeployments": 3, - "solcInputHash": "4db3e1d3dd51dbe508dc0a6a04352df6", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_validatorsCount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"NotSupported\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"minAmountForStake\",\"type\":\"uint256\"}],\"name\":\"LogMinAmountForStake\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"NUMBER_OF_VALIDATORS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ONE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TOTAL_SUPPLY\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_0\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_1\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_10\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_11\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_12\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_13\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_14\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_15\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_16\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_17\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_18\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_2\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_3\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_4\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_5\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_6\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_7\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_8\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_9\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_ix\",\"type\":\"uint256\"}],\"name\":\"addresses\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validator\",\"type\":\"address\"}],\"name\":\"balances\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"create\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"exit\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBalances\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"allBalances\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumberOfValidators\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"receiveApproval\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"register\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"remove\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"setMinAmountForStake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"stake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"update\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_id\",\"type\":\"address\"}],\"name\":\"validators\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"location\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_validators\",\"type\":\"address[]\"}],\"name\":\"verifyValidators\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addresses(uint256)\":{\"details\":\"gets validator address for provided index\",\"params\":{\"_ix\":\"index in array of list of all validators wallets\"}},\"balanceOf(address)\":{\"details\":\"to follow ERC20 interface\"},\"exit()\":{\"details\":\"unstake and withdraw all tokens\"},\"getName()\":{\"details\":\"to follow Registrable interface\"},\"getNumberOfValidators()\":{\"returns\":{\"_0\":\"total number of registered validators (with and without balance)\"}},\"register()\":{\"details\":\"to follow Registrable interface\"},\"totalSupply()\":{\"details\":\"to follow ERC20 interface\"},\"unregister()\":{\"details\":\"to follow Registrable interface\"},\"validators(address)\":{\"params\":{\"_id\":\"address of validator\"},\"returns\":{\"id\":\"address of validator\",\"location\":\"URL of validator\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":\"StakingBankStaticProd\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":0},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBank.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IStakingBank is IERC20 {\\n /// @param id address of validator wallet\\n /// @param location URL of the validator API\\n struct Validator {\\n address id;\\n string location;\\n }\\n\\n event LogValidatorRegistered(address indexed id);\\n event LogValidatorUpdated(address indexed id);\\n event LogValidatorRemoved(address indexed id);\\n event LogMinAmountForStake(uint256 minAmountForStake);\\n\\n /// @dev setter for `minAmountForStake`\\n function setMinAmountForStake(uint256 _minAmountForStake) external;\\n\\n /// @dev allows to stake `token` by validators\\n /// Validator needs to approve StakingBank beforehand\\n /// @param _value amount of tokens to stake\\n function stake(uint256 _value) external;\\n\\n /// @dev notification about approval from `_from` address on UMB token\\n /// Staking bank will stake max approved amount from `_from` address\\n /// @param _from address which approved token spend for IStakingBank\\n function receiveApproval(address _from) external returns (bool success);\\n\\n /// @dev withdraws stake tokens\\n /// it throws, when balance will be less than required minimum for stake\\n /// to withdraw all use `exit`\\n function withdraw(uint256 _value) external returns (bool success);\\n\\n /// @dev unstake and withdraw all tokens\\n function exit() external returns (bool success);\\n\\n /// @dev creates (register) new validator\\n /// @param _id validator address\\n /// @param _location location URL of the validator API\\n function create(address _id, string calldata _location) external;\\n\\n /// @dev removes validator\\n /// @param _id validator wallet\\n function remove(address _id) external;\\n\\n /// @dev updates validator location\\n /// @param _id validator wallet\\n /// @param _location new validator URL\\n function update(address _id, string calldata _location) external;\\n\\n /// @return total number of registered validators (with and without balance)\\n function getNumberOfValidators() external view returns (uint256);\\n\\n /// @dev gets validator address for provided index\\n /// @param _ix index in array of list of all validators wallets\\n function addresses(uint256 _ix) external view returns (address);\\n\\n /// @param _id address of validator\\n /// @return id address of validator\\n /// @return location URL of validator\\n function validators(address _id) external view returns (address id, string memory location);\\n}\\n\",\"keccak256\":\"0x2c518aeab8b0b3a364fafaec559d3ff0dc6a119f8d203fa31ef7ad667ca0f7b9\",\"license\":\"MIT\"},\"contracts/interfaces/StakingBankStaticNotSupported.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./IStakingBank.sol\\\";\\n\\nabstract contract StakingBankStaticNotSupported is IStakingBank {\\n error NotSupported();\\n\\n function create(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function update(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function remove(address) external pure {\\n revert NotSupported();\\n }\\n\\n function transfer(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function transferFrom(address, address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function receiveApproval(address) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function allowance(address, address) external pure returns (uint256) {\\n revert NotSupported();\\n }\\n\\n function approve(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function stake(uint256) external pure {\\n revert NotSupported();\\n }\\n\\n function withdraw(uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function exit() external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function setMinAmountForStake(uint256) external pure {\\n revert NotSupported();\\n }\\n}\\n\",\"keccak256\":\"0xa899ad9000220b04bc3f63f762a9a6a76dcc09449427e7774a53f4ceda9c1cf8\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStatic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"../interfaces/StakingBankStaticNotSupported.sol\\\";\\n\\n/// @dev Because we are using PoA in UMB oracle, staked balance does not matter. What's matter is, if signer is\\n/// validator or not. In this case we can optimise `StakingBank` and make it static for better gas performance.\\nabstract contract StakingBankStatic is StakingBankStaticNotSupported {\\n uint256 public constant ONE = 1e18;\\n\\n uint256 public immutable NUMBER_OF_VALIDATORS; // solhint-disable-line var-name-mixedcase\\n uint256 public immutable TOTAL_SUPPLY; // solhint-disable-line var-name-mixedcase\\n\\n constructor(uint256 _validatorsCount) {\\n NUMBER_OF_VALIDATORS = _validatorsCount;\\n TOTAL_SUPPLY = _validatorsCount * ONE;\\n\\n _assertValidSetup(_validatorsCount);\\n }\\n\\n function balances(address _validator) external view returns (uint256) {\\n return _isValidator(_validator) ? ONE : 0;\\n }\\n\\n function verifyValidators(address[] calldata _validators) external view returns (bool) {\\n for (uint256 i; i < _validators.length;) {\\n if (!_isValidator(_validators[i])) return false;\\n unchecked { i++; }\\n }\\n\\n return true;\\n }\\n\\n function getNumberOfValidators() external view returns (uint256) {\\n return NUMBER_OF_VALIDATORS;\\n }\\n\\n function getAddresses() external view returns (address[] memory) {\\n return _addresses();\\n }\\n\\n function getBalances() external view returns (uint256[] memory allBalances) {\\n allBalances = new uint256[](NUMBER_OF_VALIDATORS);\\n\\n for (uint256 i; i < NUMBER_OF_VALIDATORS;) {\\n allBalances[i] = ONE;\\n\\n unchecked {\\n // we will not have enough data to overflow\\n i++;\\n }\\n }\\n }\\n\\n function addresses(uint256 _ix) external view returns (address) {\\n return _addresses()[_ix];\\n }\\n\\n function validators(address _id) external view virtual returns (address id, string memory location);\\n\\n /// @dev to follow ERC20 interface\\n function balanceOf(address _account) external view returns (uint256) {\\n return _isValidator(_account) ? ONE : 0;\\n }\\n\\n /// @dev to follow ERC20 interface\\n function totalSupply() external view returns (uint256) {\\n return TOTAL_SUPPLY;\\n }\\n\\n /// @dev to follow Registrable interface\\n function getName() external pure returns (bytes32) {\\n return \\\"StakingBank\\\";\\n }\\n\\n /// @dev to follow Registrable interface\\n function register() external pure {\\n // there are no requirements atm\\n }\\n\\n /// @dev to follow Registrable interface\\n function unregister() external pure {\\n // there are no requirements atm\\n }\\n\\n function _addresses() internal view virtual returns (address[] memory);\\n\\n function _isValidator(address _validator) internal view virtual returns (bool);\\n\\n function _assertValidSetup(uint256 _validatorsCount) internal view virtual{\\n address[] memory list = _addresses();\\n require(list.length == _validatorsCount);\\n\\n for (uint256 i; i < _validatorsCount;) {\\n require(_isValidator(list[i]));\\n\\n unchecked { i ++; }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfcc53ff98b0f1c42e1bc7345a1535fdc4e938ef40d323600ead94b2ece59a381\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./StakingBankStatic.sol\\\";\\n\\ncontract StakingBankStaticProd is StakingBankStatic {\\n address public constant VALIDATOR_0 = 0x977Ba523420110e230643B772Fe9cF955e11dA7B;\\n address public constant VALIDATOR_1 = 0xe2422b23e52bc13ebA04d7FbB9F332Deb43360fB;\\n\\n // external order is based on validators submits on AVAX for Apr 2023\\n address public constant VALIDATOR_2 = 0x57F404aD75e371c1A539589C1eFCA12e0C6980AD;\\n address public constant VALIDATOR_3 = 0xD56C6A4f64E0bD70260472d1DB6Cf5825858CB0d;\\n address public constant VALIDATOR_4 = 0x220230Eda8f50067Dd9e4729345dabCCe0C61542;\\n address public constant VALIDATOR_5 = 0x93FdcAB283b0BcAc48157590af482E1CFd6af6aC;\\n address public constant VALIDATOR_6 = 0xCd733E06B06083d52fC5867E8E3432aA5c103A38;\\n address public constant VALIDATOR_7 = 0x42e210b110c6aa49CdfA7ceF1444Aa4719653111;\\n address public constant VALIDATOR_8 = 0x501731c6a69803a53Ec6c3e12f293c247cE1092B;\\n address public constant VALIDATOR_9 = 0x8bF9661F1b247522C75DD0FE84355aD2EfF27144;\\n address public constant VALIDATOR_10 = 0x281754Ab58391A478B7aA4E7f39991CfB41118c4;\\n address public constant VALIDATOR_11 = 0xB9C63a350A04d8BD245d18928a26EE036352dDd8;\\n address public constant VALIDATOR_12 = 0x57A51D5BDcE188c2295fCA3b4687475a54E65A02;\\n address public constant VALIDATOR_13 = 0x777FbA3666fa7747476a34577FcCC404b263E09F;\\n address public constant VALIDATOR_14 = 0x2F85824B2B38F179E451988670935d315b5b9692;\\n address public constant VALIDATOR_15 = 0xA7241994267682de4dE7Ef62f52dc2C783d1784B;\\n address public constant VALIDATOR_16 = 0x6eEd457C20603EDAE50C3A112CAA1a9425321bD0;\\n address public constant VALIDATOR_17 = 0xC5a7650c2725a7B6A39f15cb9FbffC7af357AFeb;\\n address public constant VALIDATOR_18 = 0xFEd95453678920c1b7b3A81F033Ca02a27225556;\\n\\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\\n\\n // solhint-disable-next-line code-complexity\\n function validators(address _id) external pure override returns (address id, string memory location) {\\n if (_id == VALIDATOR_0) return (_id, \\\"https://validator.umb.network\\\");\\n if (_id == VALIDATOR_1) return (_id, \\\"https://validator2.umb.network\\\");\\n if (_id == VALIDATOR_2) return (_id, \\\"https://umbrella.artemahr.tech\\\");\\n if (_id == VALIDATOR_3) return (_id, \\\"https://umb.vtabsolutions.com:3030\\\");\\n if (_id == VALIDATOR_4) return (_id, \\\"https://umb.stakers.world\\\");\\n if (_id == VALIDATOR_5) return (_id, \\\"https://umbrella.crazywhale.es\\\");\\n if (_id == VALIDATOR_6) return (_id, \\\"https://umbrella-node.gateomega.com\\\");\\n if (_id == VALIDATOR_7) return (_id, \\\"https://umb.anorak.technology\\\");\\n if (_id == VALIDATOR_8) return (_id, \\\"https://umbrella.validator.infstones.io\\\");\\n if (_id == VALIDATOR_9) return (_id, \\\"https://umb.hashquark.io\\\");\\n if (_id == VALIDATOR_10) return (_id, \\\"http://umbrella.staking4all.org:3000\\\");\\n if (_id == VALIDATOR_11) return (_id, \\\"https://umbrella-api.validatrium.club\\\");\\n if (_id == VALIDATOR_12) return (_id, \\\"http://5.161.78.230:3000\\\");\\n if (_id == VALIDATOR_13) return (_id, \\\"https://umbnode.blockchainliverpool.com\\\");\\n if (_id == VALIDATOR_14) return (_id, \\\"https://umb-api.staking.rocks\\\");\\n if (_id == VALIDATOR_15) return (_id, \\\"https://rpc.urbanhq.net\\\");\\n if (_id == VALIDATOR_16) return (_id, \\\"https://umbrella-node.ankastake.com\\\");\\n if (_id == VALIDATOR_17) return (_id, \\\"https://umbrella.tchambrella.com\\\");\\n if (_id == VALIDATOR_18) return (_id, \\\"https://umbrella-node.cmt13.eu\\\");\\n\\n return (address(0), \\\"\\\");\\n }\\n\\n function _addresses() internal view override returns (address[] memory) {\\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\\n\\n list[0] = VALIDATOR_0;\\n list[1] = VALIDATOR_1;\\n list[2] = VALIDATOR_2;\\n list[3] = VALIDATOR_3;\\n list[4] = VALIDATOR_4;\\n list[5] = VALIDATOR_5;\\n list[6] = VALIDATOR_6;\\n list[7] = VALIDATOR_7;\\n list[8] = VALIDATOR_8;\\n list[9] = VALIDATOR_9;\\n list[10] = VALIDATOR_10;\\n list[11] = VALIDATOR_11;\\n list[12] = VALIDATOR_12;\\n list[13] = VALIDATOR_13;\\n list[14] = VALIDATOR_14;\\n list[15] = VALIDATOR_15;\\n list[16] = VALIDATOR_16;\\n list[17] = VALIDATOR_17;\\n list[18] = VALIDATOR_18;\\n\\n return list;\\n }\\n\\n function _isValidator(address _validator) internal pure override returns (bool) {\\n return (\\n _validator == VALIDATOR_0\\n || _validator == VALIDATOR_1\\n || _validator == VALIDATOR_2\\n || _validator == VALIDATOR_3\\n || _validator == VALIDATOR_4\\n || _validator == VALIDATOR_5\\n || _validator == VALIDATOR_6\\n || _validator == VALIDATOR_7\\n || _validator == VALIDATOR_8\\n || _validator == VALIDATOR_9\\n || _validator == VALIDATOR_10\\n || _validator == VALIDATOR_11\\n || _validator == VALIDATOR_12\\n || _validator == VALIDATOR_13\\n || _validator == VALIDATOR_14\\n || _validator == VALIDATOR_15\\n || _validator == VALIDATOR_16\\n || _validator == VALIDATOR_17\\n || _validator == VALIDATOR_18\\n );\\n }\\n}\\n\",\"keccak256\":\"0x1e80a063f381fdb75109238bd1e4db75af37b5aea8d8165293aee4bf84838c85\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60c06040523480156200001157600080fd5b5060405162003da238038062003da2833981810160405281019062000037919062000eaf565b808060808181525050670de0b6b3a76400008162000056919062000f10565b60a081815250506200006e816200007660201b60201c565b505062000fcf565b600062000088620000ef60201b60201c565b9050818151146200009857600080fd5b60005b82811015620000ea57620000d2828281518110620000be57620000bd62000f71565b5b6020026020010151620008dd60201b60201c565b620000dc57600080fd5b80806001019150506200009b565b505050565b6060600060805167ffffffffffffffff81111562000112576200011162000fa0565b5b604051908082528060200260200182016040528015620001415781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b8160008151811062000170576200016f62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110620001d657620001d562000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad816002815181106200023c576200023b62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110620002a257620002a162000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073220230eda8f50067dd9e4729345dabcce0c615428160048151811062000308576200030762000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac816005815181106200036e576200036d62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a3881600681518110620003d457620003d362000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa4719653111816007815181106200043a576200043962000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b81600881518110620004a0576200049f62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff271448160098151811062000506576200050562000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600a815181106200056c576200056b62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073b9c63a350a04d8bd245d18928a26ee036352ddd881600b81518110620005d257620005d162000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600c8151811062000638576200063762000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073777fba3666fa7747476a34577fccc404b263e09f81600d815181106200069e576200069d62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600e8151811062000704576200070362000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600f815181106200076a576200076962000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081601081518110620007d057620007cf62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb8160118151811062000836576200083562000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073fed95453678920c1b7b3a81f033ca02a27225556816012815181106200089c576200089b62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806200096d575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80620009b857507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a03575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a4e575073220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a9957507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ae4575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b2f57507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b7a575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000bc55750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000c10575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000c5b575073b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ca657507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000cf1575073777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000d3c5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000d87575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000dd25750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000e1d575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000e68575073fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b600080fd5b6000819050919050565b62000e898162000e74565b811462000e9557600080fd5b50565b60008151905062000ea98162000e7e565b92915050565b60006020828403121562000ec85762000ec762000e6f565b5b600062000ed88482850162000e98565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600062000f1d8262000e74565b915062000f2a8362000e74565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161562000f665762000f6562000ee1565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60805160a051612d8a62001018600039600081816109ac0152610c2e01526000818161081b0152818161088901528181610c5401528181610dbd0152611db40152612d8a6000f3fe608060405234801561001057600080fd5b50600436106102195760003560e01c8062113e081461021e578063015f7ed61461023c57806303a1e2241461025a578063095ea7b3146102785780630db18e37146102a857806317d7de7c146102d857806318160ddd146102f65780631aa3a008146103145780631d4f9ce01461031e57806323b872dd1461034e57806327e235e31461037e57806329092d0e146103ae5780632e1a7d4d146103ca578063398b056e146103fa578063411ff4971461041857806345f9f8251461043657806352b41e351461045457806354755335146104705780635dc4bfd31461048e57806361a3e37e146104ac57806369dc7ae4146104ca57806370a08231146104e8578063838e7c3a14610518578063902d55a5146105345780639031d9131461055257806390ff7e2e14610570578063952c4f181461058e578063989b6996146105ac5780639f0e9484146105ca578063a15ab08d146105e8578063a39fac1214610604578063a694fc3a14610622578063a9059cbb1461063e578063b2119eac1461066e578063b49b08421461068c578063c2ee3a08146106aa578063db731777146106c8578063dd62ed3e146106e6578063e214a5fc14610716578063e29349d614610734578063e2dc7a1a14610752578063e79a198f14610770578063e985e0081461077a578063e9fad8ee14610798578063edf26d9b146107b6578063fa52c7d8146107e6575b600080fd5b610226610817565b6040516102339190612645565b60405180910390f35b6102446108e8565b60405161025191906126a8565b60405180910390f35b610262610900565b60405161026f91906126a8565b60405180910390f35b610292600480360381019061028d9190612725565b610918565b60405161029f9190612780565b60405180910390f35b6102c260048036038101906102bd919061279b565b61094c565b6040516102cf9190612780565b60405180910390f35b6102e0610980565b6040516102ed91906127e1565b60405180910390f35b6102fe6109a8565b60405161030b919061280b565b60405180910390f35b61031c6109d0565b005b6103386004803603810190610333919061288b565b6109d2565b6040516103459190612780565b60405180910390f35b610368600480360381019061036391906128d8565b610a38565b6040516103759190612780565b60405180910390f35b6103986004803603810190610393919061279b565b610a6c565b6040516103a5919061280b565b60405180910390f35b6103c860048036038101906103c3919061279b565b610a93565b005b6103e460048036038101906103df919061292b565b610ac5565b6040516103f19190612780565b60405180910390f35b610402610af9565b60405161040f91906126a8565b60405180910390f35b610420610b11565b60405161042d91906126a8565b60405180910390f35b61043e610b29565b60405161044b91906126a8565b60405180910390f35b61046e6004803603810190610469919061292b565b610b41565b005b610478610b73565b60405161048591906126a8565b60405180910390f35b610496610b8b565b6040516104a391906126a8565b60405180910390f35b6104b4610ba3565b6040516104c191906126a8565b60405180910390f35b6104d2610bbb565b6040516104df91906126a8565b60405180910390f35b61050260048036038101906104fd919061279b565b610bd3565b60405161050f919061280b565b60405180910390f35b610532600480360381019061052d91906129ae565b610bfa565b005b61053c610c2c565b604051610549919061280b565b60405180910390f35b61055a610c50565b604051610567919061280b565b60405180910390f35b610578610c78565b60405161058591906126a8565b60405180910390f35b610596610c90565b6040516105a391906126a8565b60405180910390f35b6105b4610ca8565b6040516105c191906126a8565b60405180910390f35b6105d2610cc0565b6040516105df91906126a8565b60405180910390f35b61060260048036038101906105fd91906129ae565b610cd8565b005b61060c610d0a565b6040516106199190612acc565b60405180910390f35b61063c6004803603810190610637919061292b565b610d19565b005b61065860048036038101906106539190612725565b610d4b565b6040516106659190612780565b60405180910390f35b610676610d7f565b60405161068391906126a8565b60405180910390f35b610694610d97565b6040516106a191906126a8565b60405180910390f35b6106b2610daf565b6040516106bf919061280b565b60405180910390f35b6106d0610dbb565b6040516106dd919061280b565b60405180910390f35b61070060048036038101906106fb9190612aee565b610ddf565b60405161070d919061280b565b60405180910390f35b61071e610e13565b60405161072b91906126a8565b60405180910390f35b61073c610e2b565b60405161074991906126a8565b60405180910390f35b61075a610e43565b60405161076791906126a8565b60405180910390f35b610778610e5b565b005b610782610e5d565b60405161078f91906126a8565b60405180910390f35b6107a0610e75565b6040516107ad9190612780565b60405180910390f35b6107d060048036038101906107cb919061292b565b610ea9565b6040516107dd91906126a8565b60405180910390f35b61080060048036038101906107fb919061279b565b610ed4565b60405161080e929190612bc7565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff81111561085357610852612bf7565b5b6040519080825280602002602001820160405280156108815781602001602082028036833780820191505090505b50905060005b7f00000000000000000000000000000000000000000000000000000000000000008110156108e457670de0b6b3a76400008282815181106108cb576108ca612c26565b5b6020026020010181815250508080600101915050610887565b5090565b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b83839050811015610a2c57610a118484838181106109f7576109f6612c26565b5b9050602002016020810190610a0c919061279b565b61182e565b610a1f576000915050610a32565b80806001019150506109d6565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a778261182e565b610a82576000610a8c565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b732f85824b2b38f179e451988670935d315b5b969281565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b73fed95453678920c1b7b3a81f033ca02a2722555681565b73777fba3666fa7747476a34577fccc404b263e09f81565b6000610bde8261182e565b610be9576000610bf3565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b73220230eda8f50067dd9e4729345dabcce0c6154281565b73a7241994267682de4de7ef62f52dc2c783d1784b81565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610d14611dae565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73281754ab58391a478b7aa4e7f39991cfb41118c481565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b736eed457c20603edae50c3a112caa1a9425321bd081565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b565b73b9c63a350a04d8bd245d18928a26ee036352ddd881565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610eb3611dae565b8281518110610ec557610ec4612c26565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f5f57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611829565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fe657826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611829565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361106d57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611829565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110d75782604051806060016040528060228152602001612c796022913991509150611829565b73220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361115e57826040518060400160405280601981526020017f68747470733a2f2f756d622e7374616b6572732e776f726c640000000000000081525091509150611829565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111e557826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611829565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361124f5782604051806060016040528060238152602001612c566023913991509150611829565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112d657826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611829565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113405782604051806060016040528060278152602001612cbf6027913991509150611829565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113c757826040518060400160405280601881526020017f68747470733a2f2f756d622e68617368717561726b2e696f000000000000000081525091509150611829565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114315782604051806060016040528060248152602001612c9b6024913991509150611829565b73b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361149b5782604051806060016040528060258152602001612ce66025913991509150611829565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152257826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611829565b73777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361158c5782604051806060016040528060278152602001612d2e6027913991509150611829565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361161357826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611829565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361169a57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611829565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036117045782604051806060016040528060238152602001612d0b6023913991509150611829565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361178b57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611829565b73fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361181257826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612d6e6f64652e636d7431332e6575000081525091509150611829565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806118bd575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061190757507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611951575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061199b575073220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806119e557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a2f575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a7957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ac3575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b0d5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b57575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ba1575073b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611beb57507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c35575073777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c7f5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611cc9575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d135750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d5d575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611da7575073fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff811115611dec57611deb612bf7565b5b604051908082528060200260200182016040528015611e1a5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611e4657611e45612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611ea957611ea8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611f0c57611f0b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611f6f57611f6e612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073220230eda8f50067dd9e4729345dabcce0c6154281600481518110611fd257611fd1612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac8160058151811061203557612034612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a388160068151811061209857612097612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa4719653111816007815181106120fb576120fa612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b8160088151811061215e5761215d612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff27144816009815181106121c1576121c0612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600a8151811061222457612223612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073b9c63a350a04d8bd245d18928a26ee036352ddd881600b8151811061228757612286612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600c815181106122ea576122e9612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073777fba3666fa7747476a34577fccc404b263e09f81600d8151811061234d5761234c612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600e815181106123b0576123af612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600f8151811061241357612412612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd08160108151811061247657612475612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb816011815181106124d9576124d8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073fed95453678920c1b7b3a81f033ca02a272255568160128151811061253c5761253b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6125bc816125a9565b82525050565b60006125ce83836125b3565b60208301905092915050565b6000602082019050919050565b60006125f28261257d565b6125fc8185612588565b935061260783612599565b8060005b8381101561263857815161261f88826125c2565b975061262a836125da565b92505060018101905061260b565b5085935050505092915050565b6000602082019050818103600083015261265f81846125e7565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061269282612667565b9050919050565b6126a281612687565b82525050565b60006020820190506126bd6000830184612699565b92915050565b600080fd5b600080fd5b6126d681612687565b81146126e157600080fd5b50565b6000813590506126f3816126cd565b92915050565b612702816125a9565b811461270d57600080fd5b50565b60008135905061271f816126f9565b92915050565b6000806040838503121561273c5761273b6126c3565b5b600061274a858286016126e4565b925050602061275b85828601612710565b9150509250929050565b60008115159050919050565b61277a81612765565b82525050565b60006020820190506127956000830184612771565b92915050565b6000602082840312156127b1576127b06126c3565b5b60006127bf848285016126e4565b91505092915050565b6000819050919050565b6127db816127c8565b82525050565b60006020820190506127f660008301846127d2565b92915050565b612805816125a9565b82525050565b600060208201905061282060008301846127fc565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261284b5761284a612826565b5b8235905067ffffffffffffffff8111156128685761286761282b565b5b60208301915083602082028301111561288457612883612830565b5b9250929050565b600080602083850312156128a2576128a16126c3565b5b600083013567ffffffffffffffff8111156128c0576128bf6126c8565b5b6128cc85828601612835565b92509250509250929050565b6000806000606084860312156128f1576128f06126c3565b5b60006128ff868287016126e4565b9350506020612910868287016126e4565b925050604061292186828701612710565b9150509250925092565b600060208284031215612941576129406126c3565b5b600061294f84828501612710565b91505092915050565b60008083601f84011261296e5761296d612826565b5b8235905067ffffffffffffffff81111561298b5761298a61282b565b5b6020830191508360018202830111156129a7576129a6612830565b5b9250929050565b6000806000604084860312156129c7576129c66126c3565b5b60006129d5868287016126e4565b935050602084013567ffffffffffffffff8111156129f6576129f56126c8565b5b612a0286828701612958565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b612a4381612687565b82525050565b6000612a558383612a3a565b60208301905092915050565b6000602082019050919050565b6000612a7982612a0e565b612a838185612a19565b9350612a8e83612a2a565b8060005b83811015612abf578151612aa68882612a49565b9750612ab183612a61565b925050600181019050612a92565b5085935050505092915050565b60006020820190508181036000830152612ae68184612a6e565b905092915050565b60008060408385031215612b0557612b046126c3565b5b6000612b13858286016126e4565b9250506020612b24858286016126e4565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612b68578082015181840152602081019050612b4d565b83811115612b77576000848401525b50505050565b6000601f19601f8301169050919050565b6000612b9982612b2e565b612ba38185612b39565b9350612bb3818560208601612b4a565b612bbc81612b7d565b840191505092915050565b6000604082019050612bdc6000830185612699565b8181036020830152612bee8184612b8e565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6170692e76616c696461747269756d2e636c756268747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6d68747470733a2f2f756d626e6f64652e626c6f636b636861696e6c69766572706f6f6c2e636f6da26469706673582212209a1752a9ea487818b8a4d658f151da9487c0cc92638142159bacde7ec2d21f7564736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102195760003560e01c8062113e081461021e578063015f7ed61461023c57806303a1e2241461025a578063095ea7b3146102785780630db18e37146102a857806317d7de7c146102d857806318160ddd146102f65780631aa3a008146103145780631d4f9ce01461031e57806323b872dd1461034e57806327e235e31461037e57806329092d0e146103ae5780632e1a7d4d146103ca578063398b056e146103fa578063411ff4971461041857806345f9f8251461043657806352b41e351461045457806354755335146104705780635dc4bfd31461048e57806361a3e37e146104ac57806369dc7ae4146104ca57806370a08231146104e8578063838e7c3a14610518578063902d55a5146105345780639031d9131461055257806390ff7e2e14610570578063952c4f181461058e578063989b6996146105ac5780639f0e9484146105ca578063a15ab08d146105e8578063a39fac1214610604578063a694fc3a14610622578063a9059cbb1461063e578063b2119eac1461066e578063b49b08421461068c578063c2ee3a08146106aa578063db731777146106c8578063dd62ed3e146106e6578063e214a5fc14610716578063e29349d614610734578063e2dc7a1a14610752578063e79a198f14610770578063e985e0081461077a578063e9fad8ee14610798578063edf26d9b146107b6578063fa52c7d8146107e6575b600080fd5b610226610817565b6040516102339190612645565b60405180910390f35b6102446108e8565b60405161025191906126a8565b60405180910390f35b610262610900565b60405161026f91906126a8565b60405180910390f35b610292600480360381019061028d9190612725565b610918565b60405161029f9190612780565b60405180910390f35b6102c260048036038101906102bd919061279b565b61094c565b6040516102cf9190612780565b60405180910390f35b6102e0610980565b6040516102ed91906127e1565b60405180910390f35b6102fe6109a8565b60405161030b919061280b565b60405180910390f35b61031c6109d0565b005b6103386004803603810190610333919061288b565b6109d2565b6040516103459190612780565b60405180910390f35b610368600480360381019061036391906128d8565b610a38565b6040516103759190612780565b60405180910390f35b6103986004803603810190610393919061279b565b610a6c565b6040516103a5919061280b565b60405180910390f35b6103c860048036038101906103c3919061279b565b610a93565b005b6103e460048036038101906103df919061292b565b610ac5565b6040516103f19190612780565b60405180910390f35b610402610af9565b60405161040f91906126a8565b60405180910390f35b610420610b11565b60405161042d91906126a8565b60405180910390f35b61043e610b29565b60405161044b91906126a8565b60405180910390f35b61046e6004803603810190610469919061292b565b610b41565b005b610478610b73565b60405161048591906126a8565b60405180910390f35b610496610b8b565b6040516104a391906126a8565b60405180910390f35b6104b4610ba3565b6040516104c191906126a8565b60405180910390f35b6104d2610bbb565b6040516104df91906126a8565b60405180910390f35b61050260048036038101906104fd919061279b565b610bd3565b60405161050f919061280b565b60405180910390f35b610532600480360381019061052d91906129ae565b610bfa565b005b61053c610c2c565b604051610549919061280b565b60405180910390f35b61055a610c50565b604051610567919061280b565b60405180910390f35b610578610c78565b60405161058591906126a8565b60405180910390f35b610596610c90565b6040516105a391906126a8565b60405180910390f35b6105b4610ca8565b6040516105c191906126a8565b60405180910390f35b6105d2610cc0565b6040516105df91906126a8565b60405180910390f35b61060260048036038101906105fd91906129ae565b610cd8565b005b61060c610d0a565b6040516106199190612acc565b60405180910390f35b61063c6004803603810190610637919061292b565b610d19565b005b61065860048036038101906106539190612725565b610d4b565b6040516106659190612780565b60405180910390f35b610676610d7f565b60405161068391906126a8565b60405180910390f35b610694610d97565b6040516106a191906126a8565b60405180910390f35b6106b2610daf565b6040516106bf919061280b565b60405180910390f35b6106d0610dbb565b6040516106dd919061280b565b60405180910390f35b61070060048036038101906106fb9190612aee565b610ddf565b60405161070d919061280b565b60405180910390f35b61071e610e13565b60405161072b91906126a8565b60405180910390f35b61073c610e2b565b60405161074991906126a8565b60405180910390f35b61075a610e43565b60405161076791906126a8565b60405180910390f35b610778610e5b565b005b610782610e5d565b60405161078f91906126a8565b60405180910390f35b6107a0610e75565b6040516107ad9190612780565b60405180910390f35b6107d060048036038101906107cb919061292b565b610ea9565b6040516107dd91906126a8565b60405180910390f35b61080060048036038101906107fb919061279b565b610ed4565b60405161080e929190612bc7565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff81111561085357610852612bf7565b5b6040519080825280602002602001820160405280156108815781602001602082028036833780820191505090505b50905060005b7f00000000000000000000000000000000000000000000000000000000000000008110156108e457670de0b6b3a76400008282815181106108cb576108ca612c26565b5b6020026020010181815250508080600101915050610887565b5090565b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b83839050811015610a2c57610a118484838181106109f7576109f6612c26565b5b9050602002016020810190610a0c919061279b565b61182e565b610a1f576000915050610a32565b80806001019150506109d6565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a778261182e565b610a82576000610a8c565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b732f85824b2b38f179e451988670935d315b5b969281565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b73fed95453678920c1b7b3a81f033ca02a2722555681565b73777fba3666fa7747476a34577fccc404b263e09f81565b6000610bde8261182e565b610be9576000610bf3565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b73220230eda8f50067dd9e4729345dabcce0c6154281565b73a7241994267682de4de7ef62f52dc2c783d1784b81565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610d14611dae565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73281754ab58391a478b7aa4e7f39991cfb41118c481565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b736eed457c20603edae50c3a112caa1a9425321bd081565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b565b73b9c63a350a04d8bd245d18928a26ee036352ddd881565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610eb3611dae565b8281518110610ec557610ec4612c26565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f5f57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611829565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fe657826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611829565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361106d57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611829565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110d75782604051806060016040528060228152602001612c796022913991509150611829565b73220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361115e57826040518060400160405280601981526020017f68747470733a2f2f756d622e7374616b6572732e776f726c640000000000000081525091509150611829565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111e557826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611829565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361124f5782604051806060016040528060238152602001612c566023913991509150611829565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112d657826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611829565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113405782604051806060016040528060278152602001612cbf6027913991509150611829565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113c757826040518060400160405280601881526020017f68747470733a2f2f756d622e68617368717561726b2e696f000000000000000081525091509150611829565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114315782604051806060016040528060248152602001612c9b6024913991509150611829565b73b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361149b5782604051806060016040528060258152602001612ce66025913991509150611829565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152257826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611829565b73777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361158c5782604051806060016040528060278152602001612d2e6027913991509150611829565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361161357826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611829565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361169a57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611829565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036117045782604051806060016040528060238152602001612d0b6023913991509150611829565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361178b57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611829565b73fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361181257826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612d6e6f64652e636d7431332e6575000081525091509150611829565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806118bd575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061190757507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611951575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061199b575073220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806119e557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a2f575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a7957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ac3575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b0d5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b57575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ba1575073b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611beb57507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c35575073777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c7f5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611cc9575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d135750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d5d575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611da7575073fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff811115611dec57611deb612bf7565b5b604051908082528060200260200182016040528015611e1a5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611e4657611e45612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611ea957611ea8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611f0c57611f0b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611f6f57611f6e612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073220230eda8f50067dd9e4729345dabcce0c6154281600481518110611fd257611fd1612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac8160058151811061203557612034612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a388160068151811061209857612097612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa4719653111816007815181106120fb576120fa612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b8160088151811061215e5761215d612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff27144816009815181106121c1576121c0612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600a8151811061222457612223612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073b9c63a350a04d8bd245d18928a26ee036352ddd881600b8151811061228757612286612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600c815181106122ea576122e9612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073777fba3666fa7747476a34577fccc404b263e09f81600d8151811061234d5761234c612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600e815181106123b0576123af612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600f8151811061241357612412612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd08160108151811061247657612475612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb816011815181106124d9576124d8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073fed95453678920c1b7b3a81f033ca02a272255568160128151811061253c5761253b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6125bc816125a9565b82525050565b60006125ce83836125b3565b60208301905092915050565b6000602082019050919050565b60006125f28261257d565b6125fc8185612588565b935061260783612599565b8060005b8381101561263857815161261f88826125c2565b975061262a836125da565b92505060018101905061260b565b5085935050505092915050565b6000602082019050818103600083015261265f81846125e7565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061269282612667565b9050919050565b6126a281612687565b82525050565b60006020820190506126bd6000830184612699565b92915050565b600080fd5b600080fd5b6126d681612687565b81146126e157600080fd5b50565b6000813590506126f3816126cd565b92915050565b612702816125a9565b811461270d57600080fd5b50565b60008135905061271f816126f9565b92915050565b6000806040838503121561273c5761273b6126c3565b5b600061274a858286016126e4565b925050602061275b85828601612710565b9150509250929050565b60008115159050919050565b61277a81612765565b82525050565b60006020820190506127956000830184612771565b92915050565b6000602082840312156127b1576127b06126c3565b5b60006127bf848285016126e4565b91505092915050565b6000819050919050565b6127db816127c8565b82525050565b60006020820190506127f660008301846127d2565b92915050565b612805816125a9565b82525050565b600060208201905061282060008301846127fc565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261284b5761284a612826565b5b8235905067ffffffffffffffff8111156128685761286761282b565b5b60208301915083602082028301111561288457612883612830565b5b9250929050565b600080602083850312156128a2576128a16126c3565b5b600083013567ffffffffffffffff8111156128c0576128bf6126c8565b5b6128cc85828601612835565b92509250509250929050565b6000806000606084860312156128f1576128f06126c3565b5b60006128ff868287016126e4565b9350506020612910868287016126e4565b925050604061292186828701612710565b9150509250925092565b600060208284031215612941576129406126c3565b5b600061294f84828501612710565b91505092915050565b60008083601f84011261296e5761296d612826565b5b8235905067ffffffffffffffff81111561298b5761298a61282b565b5b6020830191508360018202830111156129a7576129a6612830565b5b9250929050565b6000806000604084860312156129c7576129c66126c3565b5b60006129d5868287016126e4565b935050602084013567ffffffffffffffff8111156129f6576129f56126c8565b5b612a0286828701612958565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b612a4381612687565b82525050565b6000612a558383612a3a565b60208301905092915050565b6000602082019050919050565b6000612a7982612a0e565b612a838185612a19565b9350612a8e83612a2a565b8060005b83811015612abf578151612aa68882612a49565b9750612ab183612a61565b925050600181019050612a92565b5085935050505092915050565b60006020820190508181036000830152612ae68184612a6e565b905092915050565b60008060408385031215612b0557612b046126c3565b5b6000612b13858286016126e4565b9250506020612b24858286016126e4565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612b68578082015181840152602081019050612b4d565b83811115612b77576000848401525b50505050565b6000601f19601f8301169050919050565b6000612b9982612b2e565b612ba38185612b39565b9350612bb3818560208601612b4a565b612bbc81612b7d565b840191505092915050565b6000604082019050612bdc6000830185612699565b8181036020830152612bee8184612b8e565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6170692e76616c696461747269756d2e636c756268747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6d68747470733a2f2f756d626e6f64652e626c6f636b636861696e6c69766572706f6f6c2e636f6da26469706673582212209a1752a9ea487818b8a4d658f151da9487c0cc92638142159bacde7ec2d21f7564736f6c634300080d0033", + "numDeployments": 4, + "solcInputHash": "dc68422c0ad35a4fe46d461b096b9383", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_validatorsCount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"NotSupported\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"minAmountForStake\",\"type\":\"uint256\"}],\"name\":\"LogMinAmountForStake\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"NUMBER_OF_VALIDATORS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ONE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TOTAL_SUPPLY\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_0\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_1\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_10\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_11\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_12\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_13\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_14\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_2\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_3\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_4\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_5\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_6\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_7\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_8\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_9\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_ix\",\"type\":\"uint256\"}],\"name\":\"addresses\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validator\",\"type\":\"address\"}],\"name\":\"balances\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"create\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"exit\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBalances\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"allBalances\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumberOfValidators\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"receiveApproval\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"register\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"remove\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"setMinAmountForStake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"stake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"update\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_id\",\"type\":\"address\"}],\"name\":\"validators\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"location\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_validators\",\"type\":\"address[]\"}],\"name\":\"verifyValidators\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addresses(uint256)\":{\"details\":\"gets validator address for provided index\",\"params\":{\"_ix\":\"index in array of list of all validators wallets\"}},\"balanceOf(address)\":{\"details\":\"to follow ERC20 interface\"},\"exit()\":{\"details\":\"unstake and withdraw all tokens\"},\"getName()\":{\"details\":\"to follow Registrable interface\"},\"getNumberOfValidators()\":{\"returns\":{\"_0\":\"total number of registered validators (with and without balance)\"}},\"register()\":{\"details\":\"to follow Registrable interface\"},\"totalSupply()\":{\"details\":\"to follow ERC20 interface\"},\"unregister()\":{\"details\":\"to follow Registrable interface\"},\"validators(address)\":{\"params\":{\"_id\":\"address of validator\"},\"returns\":{\"id\":\"address of validator\",\"location\":\"URL of validator\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":\"StakingBankStaticProd\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":0},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBank.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IStakingBank is IERC20 {\\n /// @param id address of validator wallet\\n /// @param location URL of the validator API\\n struct Validator {\\n address id;\\n string location;\\n }\\n\\n event LogValidatorRegistered(address indexed id);\\n event LogValidatorUpdated(address indexed id);\\n event LogValidatorRemoved(address indexed id);\\n event LogMinAmountForStake(uint256 minAmountForStake);\\n\\n /// @dev setter for `minAmountForStake`\\n function setMinAmountForStake(uint256 _minAmountForStake) external;\\n\\n /// @dev allows to stake `token` by validators\\n /// Validator needs to approve StakingBank beforehand\\n /// @param _value amount of tokens to stake\\n function stake(uint256 _value) external;\\n\\n /// @dev notification about approval from `_from` address on UMB token\\n /// Staking bank will stake max approved amount from `_from` address\\n /// @param _from address which approved token spend for IStakingBank\\n function receiveApproval(address _from) external returns (bool success);\\n\\n /// @dev withdraws stake tokens\\n /// it throws, when balance will be less than required minimum for stake\\n /// to withdraw all use `exit`\\n function withdraw(uint256 _value) external returns (bool success);\\n\\n /// @dev unstake and withdraw all tokens\\n function exit() external returns (bool success);\\n\\n /// @dev creates (register) new validator\\n /// @param _id validator address\\n /// @param _location location URL of the validator API\\n function create(address _id, string calldata _location) external;\\n\\n /// @dev removes validator\\n /// @param _id validator wallet\\n function remove(address _id) external;\\n\\n /// @dev updates validator location\\n /// @param _id validator wallet\\n /// @param _location new validator URL\\n function update(address _id, string calldata _location) external;\\n\\n /// @return total number of registered validators (with and without balance)\\n function getNumberOfValidators() external view returns (uint256);\\n\\n /// @dev gets validator address for provided index\\n /// @param _ix index in array of list of all validators wallets\\n function addresses(uint256 _ix) external view returns (address);\\n\\n /// @param _id address of validator\\n /// @return id address of validator\\n /// @return location URL of validator\\n function validators(address _id) external view returns (address id, string memory location);\\n}\\n\",\"keccak256\":\"0x2c518aeab8b0b3a364fafaec559d3ff0dc6a119f8d203fa31ef7ad667ca0f7b9\",\"license\":\"MIT\"},\"contracts/interfaces/StakingBankStaticNotSupported.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./IStakingBank.sol\\\";\\n\\nabstract contract StakingBankStaticNotSupported is IStakingBank {\\n error NotSupported();\\n\\n function create(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function update(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function remove(address) external pure {\\n revert NotSupported();\\n }\\n\\n function transfer(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function transferFrom(address, address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function receiveApproval(address) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function allowance(address, address) external pure returns (uint256) {\\n revert NotSupported();\\n }\\n\\n function approve(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function stake(uint256) external pure {\\n revert NotSupported();\\n }\\n\\n function withdraw(uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function exit() external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function setMinAmountForStake(uint256) external pure {\\n revert NotSupported();\\n }\\n}\\n\",\"keccak256\":\"0xa899ad9000220b04bc3f63f762a9a6a76dcc09449427e7774a53f4ceda9c1cf8\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStatic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"../interfaces/StakingBankStaticNotSupported.sol\\\";\\n\\n/// @dev Because we are using PoA in UMB oracle, staked balance does not matter. What's matter is, if signer is\\n/// validator or not. In this case we can optimise `StakingBank` and make it static for better gas performance.\\nabstract contract StakingBankStatic is StakingBankStaticNotSupported {\\n uint256 public constant ONE = 1e18;\\n\\n uint256 public immutable NUMBER_OF_VALIDATORS; // solhint-disable-line var-name-mixedcase\\n uint256 public immutable TOTAL_SUPPLY; // solhint-disable-line var-name-mixedcase\\n\\n constructor(uint256 _validatorsCount) {\\n NUMBER_OF_VALIDATORS = _validatorsCount;\\n TOTAL_SUPPLY = _validatorsCount * ONE;\\n\\n _assertValidSetup(_validatorsCount);\\n }\\n\\n function balances(address _validator) external view returns (uint256) {\\n return _isValidator(_validator) ? ONE : 0;\\n }\\n\\n function verifyValidators(address[] calldata _validators) external view returns (bool) {\\n for (uint256 i; i < _validators.length;) {\\n if (!_isValidator(_validators[i])) return false;\\n unchecked { i++; }\\n }\\n\\n return true;\\n }\\n\\n function getNumberOfValidators() external view returns (uint256) {\\n return NUMBER_OF_VALIDATORS;\\n }\\n\\n function getAddresses() external view returns (address[] memory) {\\n return _addresses();\\n }\\n\\n function getBalances() external view returns (uint256[] memory allBalances) {\\n allBalances = new uint256[](NUMBER_OF_VALIDATORS);\\n\\n for (uint256 i; i < NUMBER_OF_VALIDATORS;) {\\n allBalances[i] = ONE;\\n\\n unchecked {\\n // we will not have enough data to overflow\\n i++;\\n }\\n }\\n }\\n\\n function addresses(uint256 _ix) external view returns (address) {\\n return _addresses()[_ix];\\n }\\n\\n function validators(address _id) external view virtual returns (address id, string memory location);\\n\\n /// @dev to follow ERC20 interface\\n function balanceOf(address _account) external view returns (uint256) {\\n return _isValidator(_account) ? ONE : 0;\\n }\\n\\n /// @dev to follow ERC20 interface\\n function totalSupply() external view returns (uint256) {\\n return TOTAL_SUPPLY;\\n }\\n\\n /// @dev to follow Registrable interface\\n function getName() external pure returns (bytes32) {\\n return \\\"StakingBank\\\";\\n }\\n\\n /// @dev to follow Registrable interface\\n function register() external pure {\\n // there are no requirements atm\\n }\\n\\n /// @dev to follow Registrable interface\\n function unregister() external pure {\\n // there are no requirements atm\\n }\\n\\n function _addresses() internal view virtual returns (address[] memory);\\n\\n function _isValidator(address _validator) internal view virtual returns (bool);\\n\\n function _assertValidSetup(uint256 _validatorsCount) internal view virtual{\\n address[] memory list = _addresses();\\n require(list.length == _validatorsCount);\\n\\n for (uint256 i; i < _validatorsCount;) {\\n require(_isValidator(list[i]));\\n\\n unchecked { i ++; }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfcc53ff98b0f1c42e1bc7345a1535fdc4e938ef40d323600ead94b2ece59a381\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./StakingBankStatic.sol\\\";\\n\\ncontract StakingBankStaticProd is StakingBankStatic {\\n address public constant VALIDATOR_0 = 0x977Ba523420110e230643B772Fe9cF955e11dA7B;\\n address public constant VALIDATOR_1 = 0xe2422b23e52bc13ebA04d7FbB9F332Deb43360fB;\\n\\n // external order is based on validators submits on AVAX for Apr 2023\\n address public constant VALIDATOR_2 = 0x57F404aD75e371c1A539589C1eFCA12e0C6980AD;\\n address public constant VALIDATOR_3 = 0xD56C6A4f64E0bD70260472d1DB6Cf5825858CB0d;\\n address public constant VALIDATOR_4 = 0x93FdcAB283b0BcAc48157590af482E1CFd6af6aC;\\n address public constant VALIDATOR_5 = 0xCd733E06B06083d52fC5867E8E3432aA5c103A38;\\n address public constant VALIDATOR_6 = 0x42e210b110c6aa49CdfA7ceF1444Aa4719653111;\\n address public constant VALIDATOR_7 = 0x501731c6a69803a53Ec6c3e12f293c247cE1092B;\\n address public constant VALIDATOR_8 = 0x8bF9661F1b247522C75DD0FE84355aD2EfF27144;\\n address public constant VALIDATOR_9 = 0x281754Ab58391A478B7aA4E7f39991CfB41118c4;\\n address public constant VALIDATOR_10 = 0x57A51D5BDcE188c2295fCA3b4687475a54E65A02;\\n address public constant VALIDATOR_11 = 0x2F85824B2B38F179E451988670935d315b5b9692;\\n address public constant VALIDATOR_12 = 0xA7241994267682de4dE7Ef62f52dc2C783d1784B;\\n address public constant VALIDATOR_13 = 0x6eEd457C20603EDAE50C3A112CAA1a9425321bD0;\\n address public constant VALIDATOR_14 = 0xC5a7650c2725a7B6A39f15cb9FbffC7af357AFeb;\\n\\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\\n\\n // solhint-disable-next-line code-complexity\\n function validators(address _id) external pure override returns (address id, string memory location) {\\n if (_id == VALIDATOR_0) return (_id, \\\"https://validator.umb.network\\\");\\n if (_id == VALIDATOR_1) return (_id, \\\"https://validator2.umb.network\\\");\\n if (_id == VALIDATOR_2) return (_id, \\\"https://umbrella.artemahr.tech\\\");\\n if (_id == VALIDATOR_3) return (_id, \\\"https://umb.vtabsolutions.com:3030\\\");\\n if (_id == VALIDATOR_4) return (_id, \\\"https://umbrella.crazywhale.es\\\");\\n if (_id == VALIDATOR_5) return (_id, \\\"https://umbrella-node.gateomega.com\\\");\\n if (_id == VALIDATOR_6) return (_id, \\\"https://umb.anorak.technology\\\");\\n if (_id == VALIDATOR_7) return (_id, \\\"https://umbrella.validator.infstones.io\\\");\\n if (_id == VALIDATOR_8) return (_id, \\\"https://umb.hashkey.cloud\\\");\\n if (_id == VALIDATOR_9) return (_id, \\\"http://umbrella.staking4all.org:3000\\\");\\n if (_id == VALIDATOR_10) return (_id, \\\"http://5.161.78.230:3000\\\");\\n if (_id == VALIDATOR_11) return (_id, \\\"https://umb-api.staking.rocks\\\");\\n if (_id == VALIDATOR_12) return (_id, \\\"https://rpc.urbanhq.net\\\");\\n if (_id == VALIDATOR_13) return (_id, \\\"https://umbrella-node.ankastake.com\\\");\\n if (_id == VALIDATOR_14) return (_id, \\\"https://umbrella.tchambrella.com\\\");\\n\\n return (address(0), \\\"\\\");\\n }\\n\\n function _addresses() internal view override returns (address[] memory) {\\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\\n\\n list[0] = VALIDATOR_0;\\n list[1] = VALIDATOR_1;\\n list[2] = VALIDATOR_2;\\n list[3] = VALIDATOR_3;\\n list[4] = VALIDATOR_4;\\n list[5] = VALIDATOR_5;\\n list[6] = VALIDATOR_6;\\n list[7] = VALIDATOR_7;\\n list[8] = VALIDATOR_8;\\n list[9] = VALIDATOR_9;\\n list[10] = VALIDATOR_10;\\n list[11] = VALIDATOR_11;\\n list[12] = VALIDATOR_12;\\n list[13] = VALIDATOR_13;\\n list[14] = VALIDATOR_14;\\n\\n return list;\\n }\\n\\n function _isValidator(address _validator) internal pure override returns (bool) {\\n return (\\n _validator == VALIDATOR_0\\n || _validator == VALIDATOR_1\\n || _validator == VALIDATOR_2\\n || _validator == VALIDATOR_3\\n || _validator == VALIDATOR_4\\n || _validator == VALIDATOR_5\\n || _validator == VALIDATOR_6\\n || _validator == VALIDATOR_7\\n || _validator == VALIDATOR_8\\n || _validator == VALIDATOR_9\\n || _validator == VALIDATOR_10\\n || _validator == VALIDATOR_11\\n || _validator == VALIDATOR_12\\n || _validator == VALIDATOR_13\\n || _validator == VALIDATOR_14\\n );\\n }\\n}\\n\",\"keccak256\":\"0xcf8016c7d7325800fb6ac9f7afd34804b738daded6239139b23f894855a4f98b\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c06040523480156200001157600080fd5b50604051620034f8380380620034f8833981810160405281019062000037919062000beb565b808060808181525050670de0b6b3a76400008162000056919062000c4c565b60a081815250506200006e816200007660201b60201c565b505062000d0b565b600062000088620000ef60201b60201c565b9050818151146200009857600080fd5b60005b82811015620000ea57620000d2828281518110620000be57620000bd62000cad565b5b60200260200101516200074560201b60201c565b620000dc57600080fd5b80806001019150506200009b565b505050565b6060600060805167ffffffffffffffff81111562000112576200011162000cdc565b5b604051908082528060200260200182016040528015620001415781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b8160008151811062000170576200016f62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110620001d657620001d562000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad816002815181106200023c576200023b62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110620002a257620002a162000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac8160048151811062000308576200030762000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a38816005815181106200036e576200036d62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa471965311181600681518110620003d457620003d362000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b816007815181106200043a576200043962000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff2714481600881518110620004a0576200049f62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c48160098151811062000506576200050562000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600a815181106200056c576200056b62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600b81518110620005d257620005d162000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600c8151811062000638576200063762000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081600d815181106200069e576200069d62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81600e8151811062000704576200070362000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480620007d5575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806200082057507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806200086b575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80620008b657507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000901575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806200094c57507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000997575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80620009e25750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a2d575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a7857507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ac35750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b0e575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b595750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ba4575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b600080fd5b6000819050919050565b62000bc58162000bb0565b811462000bd157600080fd5b50565b60008151905062000be58162000bba565b92915050565b60006020828403121562000c045762000c0362000bab565b5b600062000c148482850162000bd4565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600062000c598262000bb0565b915062000c668362000bb0565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161562000ca25762000ca162000c1d565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60805160a0516127a462000d54600039600081816109080152610b72015260008181610777015281816107e501528181610b9801528181610ce901526119a601526127a46000f3fe608060405234801561001057600080fd5b50600436106101ed5760003560e01c8062113e08146101f2578063015f7ed61461021057806303a1e2241461022e578063095ea7b31461024c5780630db18e371461027c57806317d7de7c146102ac57806318160ddd146102ca5780631aa3a008146102e85780631d4f9ce0146102f257806323b872dd1461032257806327e235e31461035257806329092d0e146103825780632e1a7d4d1461039e578063398b056e146103ce578063411ff497146103ec57806345f9f8251461040a57806352b41e351461042857806354755335146104445780635dc4bfd31461046257806369dc7ae41461048057806370a082311461049e578063838e7c3a146104ce578063902d55a5146104ea5780639031d9131461050857806390ff7e2e14610526578063989b6996146105445780639f0e948414610562578063a15ab08d14610580578063a39fac121461059c578063a694fc3a146105ba578063a9059cbb146105d6578063b2119eac14610606578063b49b084214610624578063c2ee3a0814610642578063db73177714610660578063dd62ed3e1461067e578063e2dc7a1a146106ae578063e79a198f146106cc578063e985e008146106d6578063e9fad8ee146106f4578063edf26d9b14610712578063fa52c7d814610742575b600080fd5b6101fa610773565b60405161020791906120ab565b60405180910390f35b610218610844565b604051610225919061210e565b60405180910390f35b61023661085c565b604051610243919061210e565b60405180910390f35b6102666004803603810190610261919061218b565b610874565b60405161027391906121e6565b60405180910390f35b61029660048036038101906102919190612201565b6108a8565b6040516102a391906121e6565b60405180910390f35b6102b46108dc565b6040516102c19190612247565b60405180910390f35b6102d2610904565b6040516102df9190612271565b60405180910390f35b6102f061092c565b005b61030c600480360381019061030791906122f1565b61092e565b60405161031991906121e6565b60405180910390f35b61033c6004803603810190610337919061233e565b610994565b60405161034991906121e6565b60405180910390f35b61036c60048036038101906103679190612201565b6109c8565b6040516103799190612271565b60405180910390f35b61039c60048036038101906103979190612201565b6109ef565b005b6103b860048036038101906103b39190612391565b610a21565b6040516103c591906121e6565b60405180910390f35b6103d6610a55565b6040516103e3919061210e565b60405180910390f35b6103f4610a6d565b604051610401919061210e565b60405180910390f35b610412610a85565b60405161041f919061210e565b60405180910390f35b610442600480360381019061043d9190612391565b610a9d565b005b61044c610acf565b604051610459919061210e565b60405180910390f35b61046a610ae7565b604051610477919061210e565b60405180910390f35b610488610aff565b604051610495919061210e565b60405180910390f35b6104b860048036038101906104b39190612201565b610b17565b6040516104c59190612271565b60405180910390f35b6104e860048036038101906104e39190612414565b610b3e565b005b6104f2610b70565b6040516104ff9190612271565b60405180910390f35b610510610b94565b60405161051d9190612271565b60405180910390f35b61052e610bbc565b60405161053b919061210e565b60405180910390f35b61054c610bd4565b604051610559919061210e565b60405180910390f35b61056a610bec565b604051610577919061210e565b60405180910390f35b61059a60048036038101906105959190612414565b610c04565b005b6105a4610c36565b6040516105b19190612532565b60405180910390f35b6105d460048036038101906105cf9190612391565b610c45565b005b6105f060048036038101906105eb919061218b565b610c77565b6040516105fd91906121e6565b60405180910390f35b61060e610cab565b60405161061b919061210e565b60405180910390f35b61062c610cc3565b604051610639919061210e565b60405180910390f35b61064a610cdb565b6040516106579190612271565b60405180910390f35b610668610ce7565b6040516106759190612271565b60405180910390f35b61069860048036038101906106939190612554565b610d0b565b6040516106a59190612271565b60405180910390f35b6106b6610d3f565b6040516106c3919061210e565b60405180910390f35b6106d4610d57565b005b6106de610d59565b6040516106eb919061210e565b60405180910390f35b6106fc610d71565b60405161070991906121e6565b60405180910390f35b61072c60048036038101906107279190612391565b610da5565b604051610739919061210e565b60405180910390f35b61075c60048036038101906107579190612201565b610dd0565b60405161076a92919061262d565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156107af576107ae61265d565b5b6040519080825280602002602001820160405280156107dd5781602001602082028036833780820191505090505b50905060005b7f000000000000000000000000000000000000000000000000000000000000000081101561084057670de0b6b3a76400008282815181106108275761082661268c565b5b60200260200101818152505080806001019150506107e3565b5090565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b838390508110156109885761096d8484838181106109535761095261268c565b5b90506020020160208101906109689190612201565b611548565b61097b57600091505061098e565b8080600101915050610932565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006109d382611548565b6109de5760006109e8565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73a7241994267682de4de7ef62f52dc2c783d1784b81565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b736eed457c20603edae50c3a112caa1a9425321bd081565b6000610b2282611548565b610b2d576000610b37565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73281754ab58391a478b7aa4e7f39991cfb41118c481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610c406119a0565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b565b732f85824b2b38f179e451988670935d315b5b969281565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610daf6119a0565b8281518110610dc157610dc061268c565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e5b57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611543565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610ee257826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611543565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f6957826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611543565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fd357826040518060600160405280602281526020016126df6022913991509150611543565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361105a57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611543565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110c457826040518060600160405280602381526020016126bc6023913991509150611543565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361114b57826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611543565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111b557826040518060600160405280602781526020016127256027913991509150611543565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361123c57826040518060400160405280601981526020017f68747470733a2f2f756d622e686173686b65792e636c6f75640000000000000081525091509150611543565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112a657826040518060600160405280602481526020016127016024913991509150611543565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361132d57826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611543565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113b457826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611543565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361143b57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611543565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114a5578260405180606001604052806023815260200161274c6023913991509150611543565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152c57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611543565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806115d7575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061162157507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061166b575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116b557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116ff575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061174957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611793575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806117dd5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611827575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061187157507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806118bb5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611905575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061194f5750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611999575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156119de576119dd61265d565b5b604051908082528060200260200182016040528015611a0c5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611a3857611a3761268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611a9b57611a9a61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611afe57611afd61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611b6157611b6061268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac81600481518110611bc457611bc361268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a3881600581518110611c2757611c2661268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa471965311181600681518110611c8a57611c8961268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b81600781518110611ced57611cec61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff2714481600881518110611d5057611d4f61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600981518110611db357611db261268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600a81518110611e1657611e1561268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600b81518110611e7957611e7861268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600c81518110611edc57611edb61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081600d81518110611f3f57611f3e61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81600e81518110611fa257611fa161268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6120228161200f565b82525050565b60006120348383612019565b60208301905092915050565b6000602082019050919050565b600061205882611fe3565b6120628185611fee565b935061206d83611fff565b8060005b8381101561209e5781516120858882612028565b975061209083612040565b925050600181019050612071565b5085935050505092915050565b600060208201905081810360008301526120c5818461204d565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006120f8826120cd565b9050919050565b612108816120ed565b82525050565b600060208201905061212360008301846120ff565b92915050565b600080fd5b600080fd5b61213c816120ed565b811461214757600080fd5b50565b60008135905061215981612133565b92915050565b6121688161200f565b811461217357600080fd5b50565b6000813590506121858161215f565b92915050565b600080604083850312156121a2576121a1612129565b5b60006121b08582860161214a565b92505060206121c185828601612176565b9150509250929050565b60008115159050919050565b6121e0816121cb565b82525050565b60006020820190506121fb60008301846121d7565b92915050565b60006020828403121561221757612216612129565b5b60006122258482850161214a565b91505092915050565b6000819050919050565b6122418161222e565b82525050565b600060208201905061225c6000830184612238565b92915050565b61226b8161200f565b82525050565b60006020820190506122866000830184612262565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126122b1576122b061228c565b5b8235905067ffffffffffffffff8111156122ce576122cd612291565b5b6020830191508360208202830111156122ea576122e9612296565b5b9250929050565b6000806020838503121561230857612307612129565b5b600083013567ffffffffffffffff8111156123265761232561212e565b5b6123328582860161229b565b92509250509250929050565b60008060006060848603121561235757612356612129565b5b60006123658682870161214a565b93505060206123768682870161214a565b925050604061238786828701612176565b9150509250925092565b6000602082840312156123a7576123a6612129565b5b60006123b584828501612176565b91505092915050565b60008083601f8401126123d4576123d361228c565b5b8235905067ffffffffffffffff8111156123f1576123f0612291565b5b60208301915083600182028301111561240d5761240c612296565b5b9250929050565b60008060006040848603121561242d5761242c612129565b5b600061243b8682870161214a565b935050602084013567ffffffffffffffff81111561245c5761245b61212e565b5b612468868287016123be565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6124a9816120ed565b82525050565b60006124bb83836124a0565b60208301905092915050565b6000602082019050919050565b60006124df82612474565b6124e9818561247f565b93506124f483612490565b8060005b8381101561252557815161250c88826124af565b9750612517836124c7565b9250506001810190506124f8565b5085935050505092915050565b6000602082019050818103600083015261254c81846124d4565b905092915050565b6000806040838503121561256b5761256a612129565b5b60006125798582860161214a565b925050602061258a8582860161214a565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156125ce5780820151818401526020810190506125b3565b838111156125dd576000848401525b50505050565b6000601f19601f8301169050919050565b60006125ff82612594565b612609818561259f565b93506126198185602086016125b0565b612622816125e3565b840191505092915050565b600060408201905061264260008301856120ff565b818103602083015261265481846125f4565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6da2646970667358221220b875faa4ff94a6ed380db1c82cfc4fcfdce28d00988b3f85c113e0332affbaa264736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101ed5760003560e01c8062113e08146101f2578063015f7ed61461021057806303a1e2241461022e578063095ea7b31461024c5780630db18e371461027c57806317d7de7c146102ac57806318160ddd146102ca5780631aa3a008146102e85780631d4f9ce0146102f257806323b872dd1461032257806327e235e31461035257806329092d0e146103825780632e1a7d4d1461039e578063398b056e146103ce578063411ff497146103ec57806345f9f8251461040a57806352b41e351461042857806354755335146104445780635dc4bfd31461046257806369dc7ae41461048057806370a082311461049e578063838e7c3a146104ce578063902d55a5146104ea5780639031d9131461050857806390ff7e2e14610526578063989b6996146105445780639f0e948414610562578063a15ab08d14610580578063a39fac121461059c578063a694fc3a146105ba578063a9059cbb146105d6578063b2119eac14610606578063b49b084214610624578063c2ee3a0814610642578063db73177714610660578063dd62ed3e1461067e578063e2dc7a1a146106ae578063e79a198f146106cc578063e985e008146106d6578063e9fad8ee146106f4578063edf26d9b14610712578063fa52c7d814610742575b600080fd5b6101fa610773565b60405161020791906120ab565b60405180910390f35b610218610844565b604051610225919061210e565b60405180910390f35b61023661085c565b604051610243919061210e565b60405180910390f35b6102666004803603810190610261919061218b565b610874565b60405161027391906121e6565b60405180910390f35b61029660048036038101906102919190612201565b6108a8565b6040516102a391906121e6565b60405180910390f35b6102b46108dc565b6040516102c19190612247565b60405180910390f35b6102d2610904565b6040516102df9190612271565b60405180910390f35b6102f061092c565b005b61030c600480360381019061030791906122f1565b61092e565b60405161031991906121e6565b60405180910390f35b61033c6004803603810190610337919061233e565b610994565b60405161034991906121e6565b60405180910390f35b61036c60048036038101906103679190612201565b6109c8565b6040516103799190612271565b60405180910390f35b61039c60048036038101906103979190612201565b6109ef565b005b6103b860048036038101906103b39190612391565b610a21565b6040516103c591906121e6565b60405180910390f35b6103d6610a55565b6040516103e3919061210e565b60405180910390f35b6103f4610a6d565b604051610401919061210e565b60405180910390f35b610412610a85565b60405161041f919061210e565b60405180910390f35b610442600480360381019061043d9190612391565b610a9d565b005b61044c610acf565b604051610459919061210e565b60405180910390f35b61046a610ae7565b604051610477919061210e565b60405180910390f35b610488610aff565b604051610495919061210e565b60405180910390f35b6104b860048036038101906104b39190612201565b610b17565b6040516104c59190612271565b60405180910390f35b6104e860048036038101906104e39190612414565b610b3e565b005b6104f2610b70565b6040516104ff9190612271565b60405180910390f35b610510610b94565b60405161051d9190612271565b60405180910390f35b61052e610bbc565b60405161053b919061210e565b60405180910390f35b61054c610bd4565b604051610559919061210e565b60405180910390f35b61056a610bec565b604051610577919061210e565b60405180910390f35b61059a60048036038101906105959190612414565b610c04565b005b6105a4610c36565b6040516105b19190612532565b60405180910390f35b6105d460048036038101906105cf9190612391565b610c45565b005b6105f060048036038101906105eb919061218b565b610c77565b6040516105fd91906121e6565b60405180910390f35b61060e610cab565b60405161061b919061210e565b60405180910390f35b61062c610cc3565b604051610639919061210e565b60405180910390f35b61064a610cdb565b6040516106579190612271565b60405180910390f35b610668610ce7565b6040516106759190612271565b60405180910390f35b61069860048036038101906106939190612554565b610d0b565b6040516106a59190612271565b60405180910390f35b6106b6610d3f565b6040516106c3919061210e565b60405180910390f35b6106d4610d57565b005b6106de610d59565b6040516106eb919061210e565b60405180910390f35b6106fc610d71565b60405161070991906121e6565b60405180910390f35b61072c60048036038101906107279190612391565b610da5565b604051610739919061210e565b60405180910390f35b61075c60048036038101906107579190612201565b610dd0565b60405161076a92919061262d565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156107af576107ae61265d565b5b6040519080825280602002602001820160405280156107dd5781602001602082028036833780820191505090505b50905060005b7f000000000000000000000000000000000000000000000000000000000000000081101561084057670de0b6b3a76400008282815181106108275761082661268c565b5b60200260200101818152505080806001019150506107e3565b5090565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b838390508110156109885761096d8484838181106109535761095261268c565b5b90506020020160208101906109689190612201565b611548565b61097b57600091505061098e565b8080600101915050610932565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006109d382611548565b6109de5760006109e8565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73a7241994267682de4de7ef62f52dc2c783d1784b81565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b736eed457c20603edae50c3a112caa1a9425321bd081565b6000610b2282611548565b610b2d576000610b37565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73281754ab58391a478b7aa4e7f39991cfb41118c481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610c406119a0565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b565b732f85824b2b38f179e451988670935d315b5b969281565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610daf6119a0565b8281518110610dc157610dc061268c565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e5b57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611543565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610ee257826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611543565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f6957826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611543565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fd357826040518060600160405280602281526020016126df6022913991509150611543565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361105a57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611543565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110c457826040518060600160405280602381526020016126bc6023913991509150611543565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361114b57826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611543565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111b557826040518060600160405280602781526020016127256027913991509150611543565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361123c57826040518060400160405280601981526020017f68747470733a2f2f756d622e686173686b65792e636c6f75640000000000000081525091509150611543565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112a657826040518060600160405280602481526020016127016024913991509150611543565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361132d57826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611543565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113b457826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611543565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361143b57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611543565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114a5578260405180606001604052806023815260200161274c6023913991509150611543565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152c57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611543565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806115d7575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061162157507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061166b575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116b557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116ff575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061174957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611793575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806117dd5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611827575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061187157507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806118bb5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611905575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061194f5750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611999575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156119de576119dd61265d565b5b604051908082528060200260200182016040528015611a0c5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611a3857611a3761268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611a9b57611a9a61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611afe57611afd61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611b6157611b6061268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac81600481518110611bc457611bc361268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a3881600581518110611c2757611c2661268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa471965311181600681518110611c8a57611c8961268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b81600781518110611ced57611cec61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff2714481600881518110611d5057611d4f61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600981518110611db357611db261268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600a81518110611e1657611e1561268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600b81518110611e7957611e7861268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600c81518110611edc57611edb61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081600d81518110611f3f57611f3e61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81600e81518110611fa257611fa161268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6120228161200f565b82525050565b60006120348383612019565b60208301905092915050565b6000602082019050919050565b600061205882611fe3565b6120628185611fee565b935061206d83611fff565b8060005b8381101561209e5781516120858882612028565b975061209083612040565b925050600181019050612071565b5085935050505092915050565b600060208201905081810360008301526120c5818461204d565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006120f8826120cd565b9050919050565b612108816120ed565b82525050565b600060208201905061212360008301846120ff565b92915050565b600080fd5b600080fd5b61213c816120ed565b811461214757600080fd5b50565b60008135905061215981612133565b92915050565b6121688161200f565b811461217357600080fd5b50565b6000813590506121858161215f565b92915050565b600080604083850312156121a2576121a1612129565b5b60006121b08582860161214a565b92505060206121c185828601612176565b9150509250929050565b60008115159050919050565b6121e0816121cb565b82525050565b60006020820190506121fb60008301846121d7565b92915050565b60006020828403121561221757612216612129565b5b60006122258482850161214a565b91505092915050565b6000819050919050565b6122418161222e565b82525050565b600060208201905061225c6000830184612238565b92915050565b61226b8161200f565b82525050565b60006020820190506122866000830184612262565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126122b1576122b061228c565b5b8235905067ffffffffffffffff8111156122ce576122cd612291565b5b6020830191508360208202830111156122ea576122e9612296565b5b9250929050565b6000806020838503121561230857612307612129565b5b600083013567ffffffffffffffff8111156123265761232561212e565b5b6123328582860161229b565b92509250509250929050565b60008060006060848603121561235757612356612129565b5b60006123658682870161214a565b93505060206123768682870161214a565b925050604061238786828701612176565b9150509250925092565b6000602082840312156123a7576123a6612129565b5b60006123b584828501612176565b91505092915050565b60008083601f8401126123d4576123d361228c565b5b8235905067ffffffffffffffff8111156123f1576123f0612291565b5b60208301915083600182028301111561240d5761240c612296565b5b9250929050565b60008060006040848603121561242d5761242c612129565b5b600061243b8682870161214a565b935050602084013567ffffffffffffffff81111561245c5761245b61212e565b5b612468868287016123be565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6124a9816120ed565b82525050565b60006124bb83836124a0565b60208301905092915050565b6000602082019050919050565b60006124df82612474565b6124e9818561247f565b93506124f483612490565b8060005b8381101561252557815161250c88826124af565b9750612517836124c7565b9250506001810190506124f8565b5085935050505092915050565b6000602082019050818103600083015261254c81846124d4565b905092915050565b6000806040838503121561256b5761256a612129565b5b60006125798582860161214a565b925050602061258a8582860161214a565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156125ce5780820151818401526020810190506125b3565b838111156125dd576000848401525b50505050565b6000601f19601f8301169050919050565b60006125ff82612594565b612609818561259f565b93506126198185602086016125b0565b612622816125e3565b840191505092915050565b600060408201905061264260008301856120ff565b818103602083015261265481846125f4565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6da2646970667358221220b875faa4ff94a6ed380db1c82cfc4fcfdce28d00988b3f85c113e0332affbaa264736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/base_production/UmbrellaFeeds.json b/deployments/base_production/UmbrellaFeeds.json index 8f09c029..16d83368 100644 --- a/deployments/base_production/UmbrellaFeeds.json +++ b/deployments/base_production/UmbrellaFeeds.json @@ -1,5 +1,5 @@ { - "address": "0x6d88eCDcfb14A0c352311CA4c9a33A6649752b1f", + "address": "0x0a8c66DD24B25871B2551599D6eCa859819787aa", "abi": [ { "inputs": [ @@ -662,19 +662,19 @@ "type": "function" } ], - "transactionHash": "0x58462d63e3267df8102f6c6d46739b7f4d226974f0879d7d60970dac7af0ab70", + "transactionHash": "0x83f3e39f3f935175d64c5aa24eb2b3b1d7dd27bb30f0a265683033a9f0ded63e", "receipt": { "to": null, "from": "0xA6e4fFa19B213AbeA258ae72e8e1a209B9E543e7", - "contractAddress": "0x6d88eCDcfb14A0c352311CA4c9a33A6649752b1f", - "transactionIndex": 4, - "gasUsed": "2533763", + "contractAddress": "0x0a8c66DD24B25871B2551599D6eCa859819787aa", + "transactionIndex": 88, + "gasUsed": "2534549", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x62e5047fecbdf280be9c421d20f63b50b6179e674a93f568e797539a9d36fe09", - "transactionHash": "0x58462d63e3267df8102f6c6d46739b7f4d226974f0879d7d60970dac7af0ab70", + "blockHash": "0x7ad69d7145677a355206d4e49fca1c8c0375fef758f21ba4b89d77f06c30d281", + "transactionHash": "0x83f3e39f3f935175d64c5aa24eb2b3b1d7dd27bb30f0a265683033a9f0ded63e", "logs": [], - "blockNumber": 6282530, - "cumulativeGasUsed": "3031938", + "blockNumber": 21748350, + "cumulativeGasUsed": "11951152", "status": 1, "byzantium": true }, @@ -684,7 +684,7 @@ 8 ], "numDeployments": 1, - "solcInputHash": "4db3e1d3dd51dbe508dc0a6a04352df6", + "solcInputHash": "dc68422c0ad35a4fe46d461b096b9383", "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"_contractRegistry\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"_requiredSignatures\",\"type\":\"uint16\"},{\"internalType\":\"uint8\",\"name\":\"_decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ArraysDataDoNotMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractInUse\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractNotInitialised\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ECDSAInvalidSignatureS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ECDSAInvalidSignatureV\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FeedNotExist\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRequiredSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotEnoughSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OldData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfOrder\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DECIMALS\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DEPLOYED_AT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ETH_PREFIX\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NAME\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REGISTRY\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REQUIRED_SIGNATURES\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"STAKING_BANK\",\"outputs\":[{\"internalType\":\"contract IStakingBankStatic\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"destroy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_keys\",\"type\":\"bytes32[]\"}],\"name\":\"getManyPriceData\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData[]\",\"name\":\"data\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_keys\",\"type\":\"bytes32[]\"}],\"name\":\"getManyPriceDataRaw\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData[]\",\"name\":\"data\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getPrice\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getPriceData\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData\",\"name\":\"data\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"getPriceDataByName\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData\",\"name\":\"data\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getPriceTimestamp\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getPriceTimestampHeartbeat\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_priceKeys\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData[]\",\"name\":\"_priceDatas\",\"type\":\"tuple[]\"}],\"name\":\"hashData\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"prices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData\",\"name\":\"data\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_hash\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"_v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"_r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_s\",\"type\":\"bytes32\"}],\"name\":\"recoverSigner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_priceKeys\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData[]\",\"name\":\"_priceDatas\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"struct IUmbrellaFeeds.Signature[]\",\"name\":\"_signatures\",\"type\":\"tuple[]\"}],\"name\":\"update\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_hash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"struct IUmbrellaFeeds.Signature[]\",\"name\":\"_signatures\",\"type\":\"tuple[]\"}],\"name\":\"verifySignatures\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Main contract for all on-chain data. Check `UmbrellaFeedsReader` to see how to integrate.\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_contractRegistry\":\"Registry address\",\"_decimals\":\"decimals for prices stored in this contract\",\"_requiredSignatures\":\"number of required signatures for accepting consensus submission\"}},\"destroy(string)\":{\"details\":\"destroys old contract there is sanity check that prevents abuse of destroy method\",\"params\":{\"_name\":\"string feed key to verify, that contract was initialised\"}},\"getManyPriceData(bytes32[])\":{\"details\":\"it will return array of price datas for provided `_keys` In case ony of feed does not exist, fallback call will be executed for that feed.\",\"params\":{\"_keys\":\"array of feed keys\"},\"returns\":{\"data\":\"PriceData array\"}},\"getManyPriceDataRaw(bytes32[])\":{\"details\":\"same as getManyPriceData() but does not revert on empty data.\"},\"getName()\":{\"details\":\"to follow Registrable interface\"},\"getPrice(bytes32)\":{\"params\":{\"_key\":\"hash of feed name\"},\"returns\":{\"price\":\"price\"}},\"getPriceData(bytes32)\":{\"details\":\"this is main endpoint for reading feeds. In case timestamp is empty (that means there is no data), contract will revert. If you do not need whole data from `PriceData` struct, you can save some gas by using other view methods that returns just what you need.\",\"params\":{\"_key\":\"hash of feed name\"},\"returns\":{\"data\":\"full PriceData struct\"}},\"getPriceDataByName(string)\":{\"details\":\"This method should be used only for Layer2 as it is more gas consuming than others views.\",\"params\":{\"_name\":\"string feed name\"},\"returns\":{\"data\":\"PriceData\"}},\"getPriceTimestamp(bytes32)\":{\"params\":{\"_key\":\"hash of feed name\"},\"returns\":{\"price\":\"price\",\"timestamp\":\"timestamp\"}},\"getPriceTimestampHeartbeat(bytes32)\":{\"params\":{\"_key\":\"hash of feed name\"},\"returns\":{\"heartbeat\":\"heartbeat\",\"price\":\"price\",\"timestamp\":\"timestamp\"}},\"hashData(bytes32[],(uint8,uint24,uint32,uint128)[])\":{\"details\":\"helper method for QA purposes\",\"returns\":{\"_0\":\"hash of data that are signed by validators (keys and priced data)\"}},\"prices(bytes32)\":{\"params\":{\"_key\":\"hash of feed name\"},\"returns\":{\"data\":\"full PriceData struct\"}},\"recoverSigner(bytes32,uint8,bytes32,bytes32)\":{\"params\":{\"_hash\":\"hashed of data\",\"_r\":\"part of signature\",\"_s\":\"part of signature\",\"_v\":\"part of signature\"},\"returns\":{\"_0\":\"signer address\"}},\"update(bytes32[],(uint8,uint24,uint32,uint128)[],(uint8,bytes32,bytes32)[])\":{\"details\":\"method for submitting consensus data\",\"params\":{\"_priceDatas\":\"PriceData signed by validators\",\"_priceKeys\":\"array of keys for `_priceDatas`\",\"_signatures\":\"validators signatures\"}},\"verifySignatures(bytes32,(uint8,bytes32,bytes32)[])\":{\"params\":{\"_hash\":\"hash of signed data\",\"_signatures\":\"array of validators signatures\"}}},\"stateVariables\":{\"DECIMALS\":{\"details\":\"decimals for prices stored in this contract\"},\"DEPLOYED_AT\":{\"details\":\"deployment time, used for protect for unintentional destroy\"},\"REGISTRY\":{\"details\":\"Registry contract where list of all addresses is stored. Fallback feature uses this registry to resolve newest `UmbrellaFeeds` address\"},\"REQUIRED_SIGNATURES\":{\"details\":\"minimal number of signatures required for accepting price submission (PoA)\"},\"STAKING_BANK\":{\"details\":\"StakingBank contract where list of validators is stored\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getManyPriceData(bytes32[])\":{\"notice\":\"If data for any key not exists, function will revert. Use `getManyPriceDataRaw` method if you don't want revert.\"},\"getManyPriceDataRaw(bytes32[])\":{\"notice\":\"This method does no revert if some data does not exists. Check `data.timestamp` to see if price exist, if it is 0, then it does not exist.\"},\"getPrice(bytes32)\":{\"notice\":\"method will revert if data for `_key` not exists.\"},\"getPriceData(bytes32)\":{\"notice\":\"method will revert if data for `_key` not exists.\"},\"getPriceDataByName(string)\":{\"notice\":\"It does not revert on empty data.\"},\"getPriceTimestamp(bytes32)\":{\"notice\":\"method will revert if data for `_key` not exists.\"},\"getPriceTimestampHeartbeat(bytes32)\":{\"notice\":\"method will revert if data for `_key` not exists.\"},\"prices(bytes32)\":{\"notice\":\"reader for mapping\"}},\"notice\":\"This contract can be destroyed and replaced with new one (with new address). For best gas efficiency you should pick one of two ways of integration: 1. make `UmbrellaFeeds` immutable and use fallback in case of selfdestruct. After new deployment, it is recommended to update address to avoid fallback and reduce gas cost to minimum. In long run this is most efficient solution, better than any proxy. 2. always check newest `UmbrellaFeeds` via `Regostry` and fallback will not be needed.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/onChainFeeds/UmbrellaFeeds.sol\":\"UmbrellaFeeds\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":0},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/interfaces/IRegistry.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\n\\ninterface IRegistry {\\n event LogRegistered(address indexed destination, bytes32 name);\\n\\n /// @dev imports new contract addresses and override old addresses, if they exist under provided name\\n /// This method can be used for contracts that for some reason do not have `getName` method\\n /// @param _names array of contract names that we want to register\\n /// @param _destinations array of contract addresses\\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external;\\n\\n /// @dev imports new contracts and override old addresses, if they exist.\\n /// Names of contracts are fetched directly from each contract by calling `getName`\\n /// @param _destinations array of contract addresses\\n function importContracts(address[] calldata _destinations) external;\\n\\n /// @dev this method ensure, that old and new contract is aware of it state in registry\\n /// Note: BSC registry does not have this method. This method was introduced in later stage.\\n /// @param _newContract address of contract that will replace old one\\n function atomicUpdate(address _newContract) external;\\n\\n /// @dev similar to `getAddress` but throws when contract name not exists\\n /// @param name contract name\\n /// @return contract address registered under provided name or throws, if does not exists\\n function requireAndGetAddress(bytes32 name) external view returns (address);\\n\\n /// @param name contract name in a form of bytes32\\n /// @return contract address registered under provided name\\n function getAddress(bytes32 name) external view returns (address);\\n\\n /// @param _name contract name\\n /// @return contract address assigned to the name or address(0) if not exists\\n function getAddressByString(string memory _name) external view returns (address);\\n\\n /// @dev helper method that converts string to bytes32,\\n /// you can use to to generate contract name\\n function stringToBytes32(string memory _string) external pure returns (bytes32 result);\\n}\\n\",\"keccak256\":\"0xa0099ecf4182138fda7a0733407784461410c245de67c1e7ba7cd7c9595e054f\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBank.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IStakingBank is IERC20 {\\n /// @param id address of validator wallet\\n /// @param location URL of the validator API\\n struct Validator {\\n address id;\\n string location;\\n }\\n\\n event LogValidatorRegistered(address indexed id);\\n event LogValidatorUpdated(address indexed id);\\n event LogValidatorRemoved(address indexed id);\\n event LogMinAmountForStake(uint256 minAmountForStake);\\n\\n /// @dev setter for `minAmountForStake`\\n function setMinAmountForStake(uint256 _minAmountForStake) external;\\n\\n /// @dev allows to stake `token` by validators\\n /// Validator needs to approve StakingBank beforehand\\n /// @param _value amount of tokens to stake\\n function stake(uint256 _value) external;\\n\\n /// @dev notification about approval from `_from` address on UMB token\\n /// Staking bank will stake max approved amount from `_from` address\\n /// @param _from address which approved token spend for IStakingBank\\n function receiveApproval(address _from) external returns (bool success);\\n\\n /// @dev withdraws stake tokens\\n /// it throws, when balance will be less than required minimum for stake\\n /// to withdraw all use `exit`\\n function withdraw(uint256 _value) external returns (bool success);\\n\\n /// @dev unstake and withdraw all tokens\\n function exit() external returns (bool success);\\n\\n /// @dev creates (register) new validator\\n /// @param _id validator address\\n /// @param _location location URL of the validator API\\n function create(address _id, string calldata _location) external;\\n\\n /// @dev removes validator\\n /// @param _id validator wallet\\n function remove(address _id) external;\\n\\n /// @dev updates validator location\\n /// @param _id validator wallet\\n /// @param _location new validator URL\\n function update(address _id, string calldata _location) external;\\n\\n /// @return total number of registered validators (with and without balance)\\n function getNumberOfValidators() external view returns (uint256);\\n\\n /// @dev gets validator address for provided index\\n /// @param _ix index in array of list of all validators wallets\\n function addresses(uint256 _ix) external view returns (address);\\n\\n /// @param _id address of validator\\n /// @return id address of validator\\n /// @return location URL of validator\\n function validators(address _id) external view returns (address id, string memory location);\\n}\\n\",\"keccak256\":\"0x2c518aeab8b0b3a364fafaec559d3ff0dc6a119f8d203fa31ef7ad667ca0f7b9\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBankStatic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./IStakingBank.sol\\\";\\n\\n\\ninterface IStakingBankStatic is IStakingBank {\\n /// @param _validators array of validators addresses to verify\\n /// @return TRUE when all validators are valid, FALSE otherwise\\n function verifyValidators(address[] calldata _validators) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xb7829f090205357ae8c7b86490504897060650c149309362b95eacbeef88d8ba\",\"license\":\"MIT\"},\"contracts/interfaces/IUmbrellaFeeds.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IUmbrellaFeeds {\\n struct PriceData {\\n /// @dev this is placeholder, that can be used for some additional data\\n /// atm of creating this smart contract, it is only used as marker for removed data (when == type(uint8).max)\\n uint8 data;\\n /// @dev heartbeat: how often price data will be refreshed in case price stay flat\\n uint24 heartbeat;\\n /// @dev timestamp: price time, at this time validators run consensus\\n uint32 timestamp;\\n /// @dev price\\n uint128 price;\\n }\\n\\n struct Signature {\\n uint8 v;\\n bytes32 r;\\n bytes32 s;\\n }\\n\\n /// @dev method for submitting consensus data\\n /// @param _priceKeys array of keys for `_priceDatas`\\n /// @param _priceDatas PriceData signed by validators\\n /// @param _signatures validators signatures\\n function update(\\n bytes32[] calldata _priceKeys,\\n PriceData[] calldata _priceDatas,\\n Signature[] calldata _signatures\\n ) external;\\n\\n /// @dev it will return array of price datas for provided `_keys`\\n /// In case ony of feed does not exist, fallback call will be executed for that feed.\\n /// @notice If data for any key not exists, function will revert. Use `getManyPriceDataRaw` method if you don't\\n /// want revert.\\n /// @param _keys array of feed keys\\n /// @return data PriceData array\\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data);\\n\\n /// @dev same as getManyPriceData() but does not revert on empty data.\\n /// @notice This method does no revert if some data does not exists.\\n /// Check `data.timestamp` to see if price exist, if it is 0, then it does not exist.\\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data);\\n\\n /// @dev this is main endpoint for reading feeds.\\n /// In case timestamp is empty (that means there is no data), contract will revert.\\n /// If you do not need whole data from `PriceData` struct, you can save some gas by using other view methods that\\n /// returns just what you need.\\n /// @notice method will revert if data for `_key` not exists.\\n /// @param _key hash of feed name\\n /// @return data full PriceData struct\\n function getPriceData(bytes32 _key) external view returns (PriceData memory data);\\n\\n /// @notice reader for mapping\\n /// @param _key hash of feed name\\n /// @return data full PriceData struct\\n function prices(bytes32 _key) external view returns (PriceData memory data);\\n\\n /// @notice method will revert if data for `_key` not exists.\\n /// @param _key hash of feed name\\n /// @return price\\n function getPrice(bytes32 _key) external view returns (uint128 price);\\n\\n /// @notice method will revert if data for `_key` not exists.\\n /// @param _key hash of feed name\\n /// @return price\\n /// @return timestamp\\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp);\\n\\n /// @notice method will revert if data for `_key` not exists.\\n /// @param _key hash of feed name\\n /// @return price\\n /// @return timestamp\\n /// @return heartbeat\\n function getPriceTimestampHeartbeat(bytes32 _key)\\n external\\n view\\n returns (uint128 price, uint32 timestamp, uint24 heartbeat);\\n\\n /// @dev This method should be used only for Layer2 as it is more gas consuming than others views.\\n /// @notice It does not revert on empty data.\\n /// @param _name string feed name\\n /// @return data PriceData\\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data);\\n\\n /// @dev decimals for prices stored in this contract\\n function DECIMALS() external view returns (uint8); // solhint-disable-line func-name-mixedcase\\n}\\n\",\"keccak256\":\"0x3b89742a9ab465f00aa9cf8635a5dfdc02d7ecf9bad8f564bee7c15d8aea46cb\",\"license\":\"MIT\"},\"contracts/onChainFeeds/UmbrellaFeeds.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"../interfaces/IUmbrellaFeeds.sol\\\";\\nimport \\\"../interfaces/IRegistry.sol\\\";\\nimport \\\"../interfaces/IStakingBankStatic.sol\\\";\\n\\n/// @dev Main contract for all on-chain data.\\n/// Check `UmbrellaFeedsReader` to see how to integrate.\\n///\\n/// @notice This contract can be destroyed and replaced with new one (with new address).\\n/// For best gas efficiency you should pick one of two ways of integration:\\n/// 1. make `UmbrellaFeeds` immutable and use fallback in case of selfdestruct. After new deployment, it is recommended\\n/// to update address to avoid fallback and reduce gas cost to minimum. In long run this is most efficient solution,\\n/// better than any proxy.\\n/// 2. always check newest `UmbrellaFeeds` via `Regostry` and fallback will not be needed.\\ncontract UmbrellaFeeds is IUmbrellaFeeds {\\n bytes constant public ETH_PREFIX = \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\";\\n string constant public NAME = \\\"UmbrellaFeeds\\\";\\n\\n /// @dev deployment time, used for protect for unintentional destroy\\n uint256 public immutable DEPLOYED_AT; // solhint-disable-line var-name-mixedcase\\n\\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\\n /// resolve newest `UmbrellaFeeds` address\\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\\n\\n /// @dev StakingBank contract where list of validators is stored\\n IStakingBankStatic public immutable STAKING_BANK; // solhint-disable-line var-name-mixedcase\\n\\n /// @dev minimal number of signatures required for accepting price submission (PoA)\\n uint16 public immutable REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\\n\\n /// @dev decimals for prices stored in this contract\\n uint8 public immutable DECIMALS; // solhint-disable-line var-name-mixedcase\\n\\n /// @notice map of all prices stored in this contract, key for map is hash of feed name\\n /// eg for \\\"ETH-USD\\\" feed, key will be hash(\\\"ETH-USD\\\")\\n mapping (bytes32 => PriceData) private _prices;\\n\\n error ArraysDataDoNotMatch();\\n error FeedNotExist();\\n error NotEnoughSignatures();\\n error InvalidSigner();\\n error InvalidRequiredSignatures();\\n error SignaturesOutOfOrder();\\n error ECDSAInvalidSignatureS();\\n error ECDSAInvalidSignatureV();\\n error OldData();\\n error ContractInUse();\\n error ContractNotInitialised();\\n\\n /// @param _contractRegistry Registry address\\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\\n /// @param _decimals decimals for prices stored in this contract\\n constructor(\\n IRegistry _contractRegistry,\\n uint16 _requiredSignatures,\\n uint8 _decimals\\n ) {\\n if (_requiredSignatures == 0) revert InvalidRequiredSignatures();\\n\\n REGISTRY = _contractRegistry;\\n REQUIRED_SIGNATURES = _requiredSignatures;\\n STAKING_BANK = IStakingBankStatic(_contractRegistry.requireAndGetAddress(\\\"StakingBank\\\"));\\n DECIMALS = _decimals;\\n DEPLOYED_AT = block.timestamp;\\n }\\n\\n /// @dev destroys old contract\\n /// there is sanity check that prevents abuse of destroy method\\n /// @param _name string feed key to verify, that contract was initialised\\n function destroy(string calldata _name) external {\\n if (REGISTRY.getAddressByString(NAME) == address(this)) revert ContractInUse();\\n\\n if (_prices[keccak256(abi.encodePacked(_name))].timestamp == 0 && DEPLOYED_AT + 3 days > block.timestamp) {\\n revert ContractNotInitialised();\\n }\\n\\n selfdestruct(payable(msg.sender));\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function update(\\n bytes32[] calldata _priceKeys,\\n PriceData[] calldata _priceDatas,\\n Signature[] calldata _signatures\\n ) external {\\n if (_priceKeys.length != _priceDatas.length) revert ArraysDataDoNotMatch();\\n\\n bytes32 priceDataHash = keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\\n verifySignatures(priceDataHash, _signatures);\\n\\n uint256 i;\\n\\n while (i < _priceDatas.length) {\\n bytes32 priceKey = _priceKeys[i];\\n\\n // we do not allow for older prices\\n // at the same time it prevents from reusing signatures\\n if (_prices[priceKey].timestamp >= _priceDatas[i].timestamp) revert OldData();\\n\\n _prices[priceKey] = _priceDatas[i];\\n\\n // atm there is no need for events, so in order to save gas, we do not emit any\\n unchecked { i++; }\\n }\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\\n data = new PriceData[](_keys.length);\\n\\n for (uint256 i; i < _keys.length;) {\\n data[i] = _prices[_keys[i]];\\n if (data[i].timestamp == 0) revert FeedNotExist();\\n\\n unchecked { i++; }\\n }\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\\n data = new PriceData[](_keys.length);\\n\\n for (uint256 i; i < _keys.length;) {\\n data[i] = _prices[_keys[i]];\\n unchecked { i++; }\\n }\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function prices(bytes32 _key) external view returns (PriceData memory data) {\\n data = _prices[_key];\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getPriceData(bytes32 _key) external view returns (PriceData memory data) {\\n data = _prices[_key];\\n if (data.timestamp == 0) revert FeedNotExist();\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getPrice(bytes32 _key) external view returns (uint128 price) {\\n PriceData memory data = _prices[_key];\\n if (data.timestamp == 0) revert FeedNotExist();\\n\\n return data.price;\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp) {\\n PriceData memory data = _prices[_key];\\n if (data.timestamp == 0) revert FeedNotExist();\\n\\n return (data.price, data.timestamp);\\n }\\n\\n function getPriceTimestampHeartbeat(bytes32 _key)\\n external\\n view\\n returns (uint128 price, uint32 timestamp, uint24 heartbeat)\\n {\\n PriceData memory data = _prices[_key];\\n if (data.timestamp == 0) revert FeedNotExist();\\n\\n return (data.price, data.timestamp, data.heartbeat);\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data) {\\n bytes32 key = keccak256(abi.encodePacked(_name));\\n data = _prices[key];\\n }\\n\\n /// @dev helper method for QA purposes\\n /// @return hash of data that are signed by validators (keys and priced data)\\n function hashData(bytes32[] calldata _priceKeys, PriceData[] calldata _priceDatas)\\n external\\n view\\n returns (bytes32)\\n {\\n return keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\\n }\\n\\n /// @param _hash hash of signed data\\n /// @param _signatures array of validators signatures\\n function verifySignatures(bytes32 _hash, Signature[] calldata _signatures) public view {\\n address prevSigner = address(0x0);\\n\\n if (_signatures.length < REQUIRED_SIGNATURES) revert NotEnoughSignatures();\\n\\n address[] memory validators = new address[](REQUIRED_SIGNATURES);\\n\\n // to save gas we check only required number of signatures\\n // case, where you can have part of signatures invalid but still enough valid in total is not supported\\n for (uint256 i; i < REQUIRED_SIGNATURES;) {\\n (uint8 v, bytes32 r, bytes32 s) = (_signatures[i].v, _signatures[i].r, _signatures[i].s);\\n\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n revert ECDSAInvalidSignatureS();\\n }\\n\\n if (uint8(v) != 27 && uint8(v) != 28) revert ECDSAInvalidSignatureV();\\n\\n address signer = recoverSigner(_hash, v, r, s);\\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\\n\\n // because we check only required number of signatures, any invalid one will cause revert\\n prevSigner = signer;\\n validators[i] = signer;\\n\\n unchecked { i++; }\\n }\\n\\n // bulk verification can optimise gas when we have 5 or more validators\\n if (!STAKING_BANK.verifyValidators(validators)) revert InvalidSigner();\\n }\\n\\n function getChainId() public view returns (uint256 id) {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n id := chainid()\\n }\\n }\\n\\n /// @param _hash hashed of data\\n /// @param _v part of signature\\n /// @param _r part of signature\\n /// @param _s part of signature\\n /// @return signer address\\n function recoverSigner(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _hash));\\n return ecrecover(hash, _v, _r, _s);\\n }\\n\\n /// @dev to follow Registrable interface\\n function getName() public pure returns (bytes32) {\\n return \\\"UmbrellaFeeds\\\";\\n }\\n}\\n\",\"keccak256\":\"0xf5dcfbbdfe5a5ed6e7579246363b10cdc0aa30580fec74025e0704c2b042d369\",\"license\":\"MIT\"}},\"version\":1}", "bytecode": "0x6101206040523480156200001257600080fd5b50604051620030a4380380620030a4833981810160405281019062000038919062000286565b60008261ffff160362000077576040517f458bb42100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff16815250508161ffff1660e08161ffff16815250508273ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b8152600401620000f49062000308565b602060405180830381865afa15801562000112573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000138919062000354565b73ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff16815250508060ff166101008160ff1681525050426080818152505050505062000386565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620001bd8262000190565b9050919050565b6000620001d182620001b0565b9050919050565b620001e381620001c4565b8114620001ef57600080fd5b50565b6000815190506200020381620001d8565b92915050565b600061ffff82169050919050565b620002228162000209565b81146200022e57600080fd5b50565b600081519050620002428162000217565b92915050565b600060ff82169050919050565b620002608162000248565b81146200026c57600080fd5b50565b600081519050620002808162000255565b92915050565b600080600060608486031215620002a257620002a16200018b565b5b6000620002b286828701620001f2565b9350506020620002c58682870162000231565b9250506040620002d8868287016200026f565b9150509250925092565b7f5374616b696e6742616e6b000000000000000000000000000000000000000000815250565b60006020820190506200031e60008301620002e2565b919050565b6200032e81620001b0565b81146200033a57600080fd5b50565b6000815190506200034e8162000323565b92915050565b6000602082840312156200036d576200036c6200018b565b5b60006200037d848285016200033d565b91505092915050565b60805160a05160c05160e05161010051612caf620003f560003960006108b10152600081816104e501528181610548015281816105ba01526116980152600081816107da01526116f501526000818161045e015261107e0152600081816111fd015261127a0152612caf6000f3fe608060405234801561001057600080fd5b50600436106101125760003560e01c806306433b1b1461011757806317d7de7c1461013557806324c89a491461015357806326559877146101715780632e0f26251461018d5780632e550693146101ab57806331d98b3f146101db5780633408e4701461020b578063385e05da1461022957806343fa6211146102595780635b38adc71461028957806360846bc6146102b95780636b9c3c7c146102e95780636ebb8cd2146103055780638a1194d31461032357806395f1cf301461035457806396594f66146103705780639ac18b19146103a2578063a3f4df7e146103c0578063c65a53ad146103de578063ccc6fd69146103fc578063d45167d01461042c575b600080fd5b61011f61045c565b60405161012c91906118df565b60405180910390f35b61013d610480565b60405161014a9190611913565b60405180910390f35b61015b6104a8565b60405161016891906119c7565b60405180910390f35b61018b60048036038101906101869190611a84565b6104e1565b005b6101956108af565b6040516101a29190611b00565b60405180910390f35b6101c560048036038101906101c09190611b71565b6108d3565b6040516101d29190611d39565b60405180910390f35b6101f560048036038101906101f09190611d5b565b610a54565b6040516102029190611d97565b60405180910390f35b610213610b77565b6040516102209190611dcb565b60405180910390f35b610243600480360381019061023e9190611b71565b610b7f565b6040516102509190611d39565b60405180910390f35b610273600480360381019061026e9190611d5b565b610d5e565b6040516102809190611e3b565b60405180910390f35b6102a3600480360381019061029e9190611eac565b610e7e565b6040516102b09190611e3b565b60405180910390f35b6102d360048036038101906102ce9190611d5b565b610f89565b6040516102e09190611e3b565b60405180910390f35b61030360048036038101906102fe9190611eac565b611065565b005b61030d611278565b60405161031a9190611dcb565b60405180910390f35b61033d60048036038101906103389190611d5b565b61129c565b60405161034b929190611f08565b60405180910390f35b61036e60048036038101906103699190611f87565b6113c8565b005b61038a60048036038101906103859190611d5b565b611560565b6040516103999392919061204a565b60405180910390f35b6103aa611696565b6040516103b7919061209e565b60405180910390f35b6103c86116ba565b6040516103d5919061210e565b60405180910390f35b6103e66116f3565b6040516103f39190612151565b60405180910390f35b6104166004803603810190610411919061216c565b611717565b6040516104239190611913565b60405180910390f35b61044660048036038101906104419190612219565b61175b565b60405161045391906122a1565b60405180910390f35b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f556d6272656c6c61466565647300000000000000000000000000000000000000905090565b6040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525081565b60007f000000000000000000000000000000000000000000000000000000000000000061ffff16838390501015610544576040517fe246dc6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000061ffff1667ffffffffffffffff811115610584576105836122bc565b5b6040519080825280602002602001820160405280156105b25781602001602082028036833780820191505090505b50905060005b7f000000000000000000000000000000000000000000000000000000000000000061ffff168110156107d75760008060008787858181106105fc576105fb6122eb565b5b9050606002016000016020810190610614919061231a565b888886818110610627576106266122eb565b5b90506060020160200135898987818110610644576106436122eb565b5b905060600201604001359250925092507f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08160001c11156106b1576040517f454ffaa700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601b8360ff16141580156106c95750601c8360ff1614155b15610700576040517f1afa741400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061070e8a85858561175b565b90508073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1610610775576040517f9079f69b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8096508086868151811061078c5761078b6122eb565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508480600101955050505050506105b8565b507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16631d4f9ce0826040518263ffffffff1660e01b81526004016108319190612405565b602060405180830381865afa15801561084e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610872919061245f565b6108a8576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60608282905067ffffffffffffffff8111156108f2576108f16122bc565b5b60405190808252806020026020018201604052801561092b57816020015b610918611818565b8152602001906001900390816109105790505b50905060005b83839050811015610a4d57600080858584818110610952576109516122eb565b5b9050602002013581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681525050828281518110610a3557610a346122eb565b5b60200260200101819052508080600101915050610931565b5092915050565b6000806000808481526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603610b6a576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060600151915050919050565b600046905090565b60608282905067ffffffffffffffff811115610b9e57610b9d6122bc565b5b604051908082528060200260200182016040528015610bd757816020015b610bc4611818565b815260200190600190039081610bbc5790505b50905060005b83839050811015610d5757600080858584818110610bfe57610bfd6122eb565b5b9050602002013581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681525050828281518110610ce157610ce06122eb565b5b60200260200101819052506000828281518110610d0157610d006122eb565b5b60200260200101516040015163ffffffff1603610d4a576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8080600101915050610bdd565b5092915050565b610d66611818565b6000808381526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603610e79576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b610e86611818565b60008383604051602001610e9b9291906124cb565b6040516020818303038152906040528051906020012090506000808281526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505091505092915050565b610f91611818565b6000808381526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815250509050919050565b3073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663e8f98f886040518060400160405280600d81526020017f556d6272656c6c614665656473000000000000000000000000000000000000008152506040518263ffffffff1660e01b815260040161110a919061210e565b602060405180830381865afa158015611127573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114b9190612510565b73ffffffffffffffffffffffffffffffffffffffff1603611198576040517f8c3e700900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600084846040516020016111b09291906124cb565b60405160208183030381529060405280519060200120815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff161480156112285750426203f4807f0000000000000000000000000000000000000000000000000000000000000000611226919061256c565b115b1561125f576040517fcf51b43b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff16ff5b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060008060008581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff16036113b4576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806060015181604001519250925050915091565b838390508686905014611407576040517f0cf7902300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611411610b77565b308888888860405160200161142b96959493929190612820565b60405160208183030381529060405280519060200120905061144e8184846104e1565b60005b85859050811015611556576000888883818110611471576114706122eb565b5b90506020020135905086868381811061148d5761148c6122eb565b5b90506080020160400160208101906114a59190612877565b63ffffffff1660008083815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff161061150e576040517f1251b2f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b868683818110611521576115206122eb565b5b90506080020160008083815260200190815260200160002081816115459190612ba1565b905050818060010192505050611451565b5050505050505050565b6000806000806000808681526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603611679576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806060015181604001518260200151935093509350509193909250565b7f000000000000000000000000000000000000000000000000000000000000000081565b6040518060400160405280600d81526020017f556d6272656c6c6146656564730000000000000000000000000000000000000081525081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000611721610b77565b308686868660405160200161173b96959493929190612820565b604051602081830303815290604052805190602001209050949350505050565b6000806040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250866040516020016117a6929190612c0c565b604051602081830303815290604052805190602001209050600181868686604051600081526020016040526040516117e19493929190612c34565b6020604051602081039080840390855afa158015611803573d6000803e3d6000fd5b50505060206040510351915050949350505050565b6040518060800160405280600060ff168152602001600062ffffff168152602001600063ffffffff16815260200160006fffffffffffffffffffffffffffffffff1681525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006118a56118a061189b84611860565b611880565b611860565b9050919050565b60006118b78261188a565b9050919050565b60006118c9826118ac565b9050919050565b6118d9816118be565b82525050565b60006020820190506118f460008301846118d0565b92915050565b6000819050919050565b61190d816118fa565b82525050565b60006020820190506119286000830184611904565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561196857808201518184015260208101905061194d565b83811115611977576000848401525b50505050565b6000601f19601f8301169050919050565b60006119998261192e565b6119a38185611939565b93506119b381856020860161194a565b6119bc8161197d565b840191505092915050565b600060208201905081810360008301526119e1818461198e565b905092915050565b600080fd5b600080fd5b6119fc816118fa565b8114611a0757600080fd5b50565b600081359050611a19816119f3565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112611a4457611a43611a1f565b5b8235905067ffffffffffffffff811115611a6157611a60611a24565b5b602083019150836060820283011115611a7d57611a7c611a29565b5b9250929050565b600080600060408486031215611a9d57611a9c6119e9565b5b6000611aab86828701611a0a565b935050602084013567ffffffffffffffff811115611acc57611acb6119ee565b5b611ad886828701611a2e565b92509250509250925092565b600060ff82169050919050565b611afa81611ae4565b82525050565b6000602082019050611b156000830184611af1565b92915050565b60008083601f840112611b3157611b30611a1f565b5b8235905067ffffffffffffffff811115611b4e57611b4d611a24565b5b602083019150836020820283011115611b6a57611b69611a29565b5b9250929050565b60008060208385031215611b8857611b876119e9565b5b600083013567ffffffffffffffff811115611ba657611ba56119ee565b5b611bb285828601611b1b565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b611bf381611ae4565b82525050565b600062ffffff82169050919050565b611c1181611bf9565b82525050565b600063ffffffff82169050919050565b611c3081611c17565b82525050565b60006fffffffffffffffffffffffffffffffff82169050919050565b611c5b81611c36565b82525050565b608082016000820151611c776000850182611bea565b506020820151611c8a6020850182611c08565b506040820151611c9d6040850182611c27565b506060820151611cb06060850182611c52565b50505050565b6000611cc28383611c61565b60808301905092915050565b6000602082019050919050565b6000611ce682611bbe565b611cf08185611bc9565b9350611cfb83611bda565b8060005b83811015611d2c578151611d138882611cb6565b9750611d1e83611cce565b925050600181019050611cff565b5085935050505092915050565b60006020820190508181036000830152611d538184611cdb565b905092915050565b600060208284031215611d7157611d706119e9565b5b6000611d7f84828501611a0a565b91505092915050565b611d9181611c36565b82525050565b6000602082019050611dac6000830184611d88565b92915050565b6000819050919050565b611dc581611db2565b82525050565b6000602082019050611de06000830184611dbc565b92915050565b608082016000820151611dfc6000850182611bea565b506020820151611e0f6020850182611c08565b506040820151611e226040850182611c27565b506060820151611e356060850182611c52565b50505050565b6000608082019050611e506000830184611de6565b92915050565b60008083601f840112611e6c57611e6b611a1f565b5b8235905067ffffffffffffffff811115611e8957611e88611a24565b5b602083019150836001820283011115611ea557611ea4611a29565b5b9250929050565b60008060208385031215611ec357611ec26119e9565b5b600083013567ffffffffffffffff811115611ee157611ee06119ee565b5b611eed85828601611e56565b92509250509250929050565b611f0281611c17565b82525050565b6000604082019050611f1d6000830185611d88565b611f2a6020830184611ef9565b9392505050565b60008083601f840112611f4757611f46611a1f565b5b8235905067ffffffffffffffff811115611f6457611f63611a24565b5b602083019150836080820283011115611f8057611f7f611a29565b5b9250929050565b60008060008060008060608789031215611fa457611fa36119e9565b5b600087013567ffffffffffffffff811115611fc257611fc16119ee565b5b611fce89828a01611b1b565b9650965050602087013567ffffffffffffffff811115611ff157611ff06119ee565b5b611ffd89828a01611f31565b9450945050604087013567ffffffffffffffff8111156120205761201f6119ee565b5b61202c89828a01611a2e565b92509250509295509295509295565b61204481611bf9565b82525050565b600060608201905061205f6000830186611d88565b61206c6020830185611ef9565b612079604083018461203b565b949350505050565b600061ffff82169050919050565b61209881612081565b82525050565b60006020820190506120b3600083018461208f565b92915050565b600081519050919050565b600082825260208201905092915050565b60006120e0826120b9565b6120ea81856120c4565b93506120fa81856020860161194a565b6121038161197d565b840191505092915050565b6000602082019050818103600083015261212881846120d5565b905092915050565b600061213b826118ac565b9050919050565b61214b81612130565b82525050565b60006020820190506121666000830184612142565b92915050565b60008060008060408587031215612186576121856119e9565b5b600085013567ffffffffffffffff8111156121a4576121a36119ee565b5b6121b087828801611b1b565b9450945050602085013567ffffffffffffffff8111156121d3576121d26119ee565b5b6121df87828801611f31565b925092505092959194509250565b6121f681611ae4565b811461220157600080fd5b50565b600081359050612213816121ed565b92915050565b60008060008060808587031215612233576122326119e9565b5b600061224187828801611a0a565b945050602061225287828801612204565b935050604061226387828801611a0a565b925050606061227487828801611a0a565b91505092959194509250565b600061228b82611860565b9050919050565b61229b81612280565b82525050565b60006020820190506122b66000830184612292565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156123305761232f6119e9565b5b600061233e84828501612204565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61237c81612280565b82525050565b600061238e8383612373565b60208301905092915050565b6000602082019050919050565b60006123b282612347565b6123bc8185612352565b93506123c783612363565b8060005b838110156123f85781516123df8882612382565b97506123ea8361239a565b9250506001810190506123cb565b5085935050505092915050565b6000602082019050818103600083015261241f81846123a7565b905092915050565b60008115159050919050565b61243c81612427565b811461244757600080fd5b50565b60008151905061245981612433565b92915050565b600060208284031215612475576124746119e9565b5b60006124838482850161244a565b91505092915050565b600081905092915050565b82818337600083830152505050565b60006124b2838561248c565b93506124bf838584612497565b82840190509392505050565b60006124d88284866124a6565b91508190509392505050565b6124ed81612280565b81146124f857600080fd5b50565b60008151905061250a816124e4565b92915050565b600060208284031215612526576125256119e9565b5b6000612534848285016124fb565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061257782611db2565b915061258283611db2565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156125b7576125b661253d565b5b828201905092915050565b600082825260208201905092915050565b600080fd5b60006125e483856125c2565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115612617576126166125d3565b5b602083029250612628838584612497565b82840190509392505050565b6000819050919050565b600061264d6020840184612204565b905092915050565b61265e81611bf9565b811461266957600080fd5b50565b60008135905061267b81612655565b92915050565b6000612690602084018461266c565b905092915050565b6126a181611c17565b81146126ac57600080fd5b50565b6000813590506126be81612698565b92915050565b60006126d360208401846126af565b905092915050565b6126e481611c36565b81146126ef57600080fd5b50565b600081359050612701816126db565b92915050565b600061271660208401846126f2565b905092915050565b6080820161272f600083018361263e565b61273c6000850182611bea565b5061274a6020830183612681565b6127576020850182611c08565b5061276560408301836126c4565b6127726040850182611c27565b506127806060830183612707565b61278d6060850182611c52565b50505050565b600061279f838361271e565b60808301905092915050565b600082905092915050565b6000608082019050919050565b60006127cf8385611bc9565b93506127da82612634565b8060005b85811015612813576127f082846127ab565b6127fa8882612793565b9750612805836127b6565b9250506001810190506127de565b5085925050509392505050565b60006080820190506128356000830189611dbc565b6128426020830188612292565b81810360408301526128558186886125d8565b9050818103606083015261286a8184866127c3565b9050979650505050505050565b60006020828403121561288d5761288c6119e9565b5b600061289b848285016126af565b91505092915050565b600081356128b1816121ed565b80915050919050565b60008160001b9050919050565b600060ff6128d4846128ba565b9350801983169250808416831791505092915050565b60006129056129006128fb84611ae4565b611880565b611ae4565b9050919050565b6000819050919050565b61291f826128ea565b61293261292b8261290c565b83546128c7565b8255505050565b6000813561294681612655565b80915050919050565b60008160081b9050919050565b600063ffffff0061296c8461294f565b9350801983169250808416831791505092915050565b600061299d61299861299384611bf9565b611880565b611bf9565b9050919050565b6000819050919050565b6129b782612982565b6129ca6129c3826129a4565b835461295c565b8255505050565b600081356129de81612698565b80915050919050565b60008160201b9050919050565b600067ffffffff00000000612a08846129e7565b9350801983169250808416831791505092915050565b6000612a39612a34612a2f84611c17565b611880565b611c17565b9050919050565b6000819050919050565b612a5382612a1e565b612a66612a5f82612a40565b83546129f4565b8255505050565b60008135612a7a816126db565b80915050919050565b60008160401b9050919050565b600077ffffffffffffffffffffffffffffffff0000000000000000612ab484612a83565b9350801983169250808416831791505092915050565b6000612ae5612ae0612adb84611c36565b611880565b611c36565b9050919050565b6000819050919050565b612aff82612aca565b612b12612b0b82612aec565b8354612a90565b8255505050565b600081016000830180612b2b816128a4565b9050612b378184612916565b505050600081016020830180612b4c81612939565b9050612b5881846129ae565b505050600081016040830180612b6d816129d1565b9050612b798184612a4a565b505050600081016060830180612b8e81612a6d565b9050612b9a8184612af6565b5050505050565b612bab8282612b19565b5050565b600081905092915050565b6000612bc58261192e565b612bcf8185612baf565b9350612bdf81856020860161194a565b80840191505092915050565b6000819050919050565b612c06612c01826118fa565b612beb565b82525050565b6000612c188285612bba565b9150612c248284612bf5565b6020820191508190509392505050565b6000608082019050612c496000830187611904565b612c566020830186611af1565b612c636040830185611904565b612c706060830184611904565b9594505050505056fea26469706673582212204e20478e2e3070a20aa83127753a448e1b78b26fd4b44673d2f1b4027a2cf6be64736f6c634300080d0033", "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101125760003560e01c806306433b1b1461011757806317d7de7c1461013557806324c89a491461015357806326559877146101715780632e0f26251461018d5780632e550693146101ab57806331d98b3f146101db5780633408e4701461020b578063385e05da1461022957806343fa6211146102595780635b38adc71461028957806360846bc6146102b95780636b9c3c7c146102e95780636ebb8cd2146103055780638a1194d31461032357806395f1cf301461035457806396594f66146103705780639ac18b19146103a2578063a3f4df7e146103c0578063c65a53ad146103de578063ccc6fd69146103fc578063d45167d01461042c575b600080fd5b61011f61045c565b60405161012c91906118df565b60405180910390f35b61013d610480565b60405161014a9190611913565b60405180910390f35b61015b6104a8565b60405161016891906119c7565b60405180910390f35b61018b60048036038101906101869190611a84565b6104e1565b005b6101956108af565b6040516101a29190611b00565b60405180910390f35b6101c560048036038101906101c09190611b71565b6108d3565b6040516101d29190611d39565b60405180910390f35b6101f560048036038101906101f09190611d5b565b610a54565b6040516102029190611d97565b60405180910390f35b610213610b77565b6040516102209190611dcb565b60405180910390f35b610243600480360381019061023e9190611b71565b610b7f565b6040516102509190611d39565b60405180910390f35b610273600480360381019061026e9190611d5b565b610d5e565b6040516102809190611e3b565b60405180910390f35b6102a3600480360381019061029e9190611eac565b610e7e565b6040516102b09190611e3b565b60405180910390f35b6102d360048036038101906102ce9190611d5b565b610f89565b6040516102e09190611e3b565b60405180910390f35b61030360048036038101906102fe9190611eac565b611065565b005b61030d611278565b60405161031a9190611dcb565b60405180910390f35b61033d60048036038101906103389190611d5b565b61129c565b60405161034b929190611f08565b60405180910390f35b61036e60048036038101906103699190611f87565b6113c8565b005b61038a60048036038101906103859190611d5b565b611560565b6040516103999392919061204a565b60405180910390f35b6103aa611696565b6040516103b7919061209e565b60405180910390f35b6103c86116ba565b6040516103d5919061210e565b60405180910390f35b6103e66116f3565b6040516103f39190612151565b60405180910390f35b6104166004803603810190610411919061216c565b611717565b6040516104239190611913565b60405180910390f35b61044660048036038101906104419190612219565b61175b565b60405161045391906122a1565b60405180910390f35b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f556d6272656c6c61466565647300000000000000000000000000000000000000905090565b6040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525081565b60007f000000000000000000000000000000000000000000000000000000000000000061ffff16838390501015610544576040517fe246dc6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000061ffff1667ffffffffffffffff811115610584576105836122bc565b5b6040519080825280602002602001820160405280156105b25781602001602082028036833780820191505090505b50905060005b7f000000000000000000000000000000000000000000000000000000000000000061ffff168110156107d75760008060008787858181106105fc576105fb6122eb565b5b9050606002016000016020810190610614919061231a565b888886818110610627576106266122eb565b5b90506060020160200135898987818110610644576106436122eb565b5b905060600201604001359250925092507f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08160001c11156106b1576040517f454ffaa700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601b8360ff16141580156106c95750601c8360ff1614155b15610700576040517f1afa741400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061070e8a85858561175b565b90508073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1610610775576040517f9079f69b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8096508086868151811061078c5761078b6122eb565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508480600101955050505050506105b8565b507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16631d4f9ce0826040518263ffffffff1660e01b81526004016108319190612405565b602060405180830381865afa15801561084e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610872919061245f565b6108a8576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60608282905067ffffffffffffffff8111156108f2576108f16122bc565b5b60405190808252806020026020018201604052801561092b57816020015b610918611818565b8152602001906001900390816109105790505b50905060005b83839050811015610a4d57600080858584818110610952576109516122eb565b5b9050602002013581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681525050828281518110610a3557610a346122eb565b5b60200260200101819052508080600101915050610931565b5092915050565b6000806000808481526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603610b6a576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060600151915050919050565b600046905090565b60608282905067ffffffffffffffff811115610b9e57610b9d6122bc565b5b604051908082528060200260200182016040528015610bd757816020015b610bc4611818565b815260200190600190039081610bbc5790505b50905060005b83839050811015610d5757600080858584818110610bfe57610bfd6122eb565b5b9050602002013581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681525050828281518110610ce157610ce06122eb565b5b60200260200101819052506000828281518110610d0157610d006122eb565b5b60200260200101516040015163ffffffff1603610d4a576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8080600101915050610bdd565b5092915050565b610d66611818565b6000808381526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603610e79576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b610e86611818565b60008383604051602001610e9b9291906124cb565b6040516020818303038152906040528051906020012090506000808281526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505091505092915050565b610f91611818565b6000808381526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815250509050919050565b3073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663e8f98f886040518060400160405280600d81526020017f556d6272656c6c614665656473000000000000000000000000000000000000008152506040518263ffffffff1660e01b815260040161110a919061210e565b602060405180830381865afa158015611127573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114b9190612510565b73ffffffffffffffffffffffffffffffffffffffff1603611198576040517f8c3e700900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600084846040516020016111b09291906124cb565b60405160208183030381529060405280519060200120815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff161480156112285750426203f4807f0000000000000000000000000000000000000000000000000000000000000000611226919061256c565b115b1561125f576040517fcf51b43b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff16ff5b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060008060008581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff16036113b4576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806060015181604001519250925050915091565b838390508686905014611407576040517f0cf7902300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611411610b77565b308888888860405160200161142b96959493929190612820565b60405160208183030381529060405280519060200120905061144e8184846104e1565b60005b85859050811015611556576000888883818110611471576114706122eb565b5b90506020020135905086868381811061148d5761148c6122eb565b5b90506080020160400160208101906114a59190612877565b63ffffffff1660008083815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff161061150e576040517f1251b2f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b868683818110611521576115206122eb565b5b90506080020160008083815260200190815260200160002081816115459190612ba1565b905050818060010192505050611451565b5050505050505050565b6000806000806000808681526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603611679576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806060015181604001518260200151935093509350509193909250565b7f000000000000000000000000000000000000000000000000000000000000000081565b6040518060400160405280600d81526020017f556d6272656c6c6146656564730000000000000000000000000000000000000081525081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000611721610b77565b308686868660405160200161173b96959493929190612820565b604051602081830303815290604052805190602001209050949350505050565b6000806040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250866040516020016117a6929190612c0c565b604051602081830303815290604052805190602001209050600181868686604051600081526020016040526040516117e19493929190612c34565b6020604051602081039080840390855afa158015611803573d6000803e3d6000fd5b50505060206040510351915050949350505050565b6040518060800160405280600060ff168152602001600062ffffff168152602001600063ffffffff16815260200160006fffffffffffffffffffffffffffffffff1681525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006118a56118a061189b84611860565b611880565b611860565b9050919050565b60006118b78261188a565b9050919050565b60006118c9826118ac565b9050919050565b6118d9816118be565b82525050565b60006020820190506118f460008301846118d0565b92915050565b6000819050919050565b61190d816118fa565b82525050565b60006020820190506119286000830184611904565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561196857808201518184015260208101905061194d565b83811115611977576000848401525b50505050565b6000601f19601f8301169050919050565b60006119998261192e565b6119a38185611939565b93506119b381856020860161194a565b6119bc8161197d565b840191505092915050565b600060208201905081810360008301526119e1818461198e565b905092915050565b600080fd5b600080fd5b6119fc816118fa565b8114611a0757600080fd5b50565b600081359050611a19816119f3565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112611a4457611a43611a1f565b5b8235905067ffffffffffffffff811115611a6157611a60611a24565b5b602083019150836060820283011115611a7d57611a7c611a29565b5b9250929050565b600080600060408486031215611a9d57611a9c6119e9565b5b6000611aab86828701611a0a565b935050602084013567ffffffffffffffff811115611acc57611acb6119ee565b5b611ad886828701611a2e565b92509250509250925092565b600060ff82169050919050565b611afa81611ae4565b82525050565b6000602082019050611b156000830184611af1565b92915050565b60008083601f840112611b3157611b30611a1f565b5b8235905067ffffffffffffffff811115611b4e57611b4d611a24565b5b602083019150836020820283011115611b6a57611b69611a29565b5b9250929050565b60008060208385031215611b8857611b876119e9565b5b600083013567ffffffffffffffff811115611ba657611ba56119ee565b5b611bb285828601611b1b565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b611bf381611ae4565b82525050565b600062ffffff82169050919050565b611c1181611bf9565b82525050565b600063ffffffff82169050919050565b611c3081611c17565b82525050565b60006fffffffffffffffffffffffffffffffff82169050919050565b611c5b81611c36565b82525050565b608082016000820151611c776000850182611bea565b506020820151611c8a6020850182611c08565b506040820151611c9d6040850182611c27565b506060820151611cb06060850182611c52565b50505050565b6000611cc28383611c61565b60808301905092915050565b6000602082019050919050565b6000611ce682611bbe565b611cf08185611bc9565b9350611cfb83611bda565b8060005b83811015611d2c578151611d138882611cb6565b9750611d1e83611cce565b925050600181019050611cff565b5085935050505092915050565b60006020820190508181036000830152611d538184611cdb565b905092915050565b600060208284031215611d7157611d706119e9565b5b6000611d7f84828501611a0a565b91505092915050565b611d9181611c36565b82525050565b6000602082019050611dac6000830184611d88565b92915050565b6000819050919050565b611dc581611db2565b82525050565b6000602082019050611de06000830184611dbc565b92915050565b608082016000820151611dfc6000850182611bea565b506020820151611e0f6020850182611c08565b506040820151611e226040850182611c27565b506060820151611e356060850182611c52565b50505050565b6000608082019050611e506000830184611de6565b92915050565b60008083601f840112611e6c57611e6b611a1f565b5b8235905067ffffffffffffffff811115611e8957611e88611a24565b5b602083019150836001820283011115611ea557611ea4611a29565b5b9250929050565b60008060208385031215611ec357611ec26119e9565b5b600083013567ffffffffffffffff811115611ee157611ee06119ee565b5b611eed85828601611e56565b92509250509250929050565b611f0281611c17565b82525050565b6000604082019050611f1d6000830185611d88565b611f2a6020830184611ef9565b9392505050565b60008083601f840112611f4757611f46611a1f565b5b8235905067ffffffffffffffff811115611f6457611f63611a24565b5b602083019150836080820283011115611f8057611f7f611a29565b5b9250929050565b60008060008060008060608789031215611fa457611fa36119e9565b5b600087013567ffffffffffffffff811115611fc257611fc16119ee565b5b611fce89828a01611b1b565b9650965050602087013567ffffffffffffffff811115611ff157611ff06119ee565b5b611ffd89828a01611f31565b9450945050604087013567ffffffffffffffff8111156120205761201f6119ee565b5b61202c89828a01611a2e565b92509250509295509295509295565b61204481611bf9565b82525050565b600060608201905061205f6000830186611d88565b61206c6020830185611ef9565b612079604083018461203b565b949350505050565b600061ffff82169050919050565b61209881612081565b82525050565b60006020820190506120b3600083018461208f565b92915050565b600081519050919050565b600082825260208201905092915050565b60006120e0826120b9565b6120ea81856120c4565b93506120fa81856020860161194a565b6121038161197d565b840191505092915050565b6000602082019050818103600083015261212881846120d5565b905092915050565b600061213b826118ac565b9050919050565b61214b81612130565b82525050565b60006020820190506121666000830184612142565b92915050565b60008060008060408587031215612186576121856119e9565b5b600085013567ffffffffffffffff8111156121a4576121a36119ee565b5b6121b087828801611b1b565b9450945050602085013567ffffffffffffffff8111156121d3576121d26119ee565b5b6121df87828801611f31565b925092505092959194509250565b6121f681611ae4565b811461220157600080fd5b50565b600081359050612213816121ed565b92915050565b60008060008060808587031215612233576122326119e9565b5b600061224187828801611a0a565b945050602061225287828801612204565b935050604061226387828801611a0a565b925050606061227487828801611a0a565b91505092959194509250565b600061228b82611860565b9050919050565b61229b81612280565b82525050565b60006020820190506122b66000830184612292565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156123305761232f6119e9565b5b600061233e84828501612204565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61237c81612280565b82525050565b600061238e8383612373565b60208301905092915050565b6000602082019050919050565b60006123b282612347565b6123bc8185612352565b93506123c783612363565b8060005b838110156123f85781516123df8882612382565b97506123ea8361239a565b9250506001810190506123cb565b5085935050505092915050565b6000602082019050818103600083015261241f81846123a7565b905092915050565b60008115159050919050565b61243c81612427565b811461244757600080fd5b50565b60008151905061245981612433565b92915050565b600060208284031215612475576124746119e9565b5b60006124838482850161244a565b91505092915050565b600081905092915050565b82818337600083830152505050565b60006124b2838561248c565b93506124bf838584612497565b82840190509392505050565b60006124d88284866124a6565b91508190509392505050565b6124ed81612280565b81146124f857600080fd5b50565b60008151905061250a816124e4565b92915050565b600060208284031215612526576125256119e9565b5b6000612534848285016124fb565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061257782611db2565b915061258283611db2565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156125b7576125b661253d565b5b828201905092915050565b600082825260208201905092915050565b600080fd5b60006125e483856125c2565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115612617576126166125d3565b5b602083029250612628838584612497565b82840190509392505050565b6000819050919050565b600061264d6020840184612204565b905092915050565b61265e81611bf9565b811461266957600080fd5b50565b60008135905061267b81612655565b92915050565b6000612690602084018461266c565b905092915050565b6126a181611c17565b81146126ac57600080fd5b50565b6000813590506126be81612698565b92915050565b60006126d360208401846126af565b905092915050565b6126e481611c36565b81146126ef57600080fd5b50565b600081359050612701816126db565b92915050565b600061271660208401846126f2565b905092915050565b6080820161272f600083018361263e565b61273c6000850182611bea565b5061274a6020830183612681565b6127576020850182611c08565b5061276560408301836126c4565b6127726040850182611c27565b506127806060830183612707565b61278d6060850182611c52565b50505050565b600061279f838361271e565b60808301905092915050565b600082905092915050565b6000608082019050919050565b60006127cf8385611bc9565b93506127da82612634565b8060005b85811015612813576127f082846127ab565b6127fa8882612793565b9750612805836127b6565b9250506001810190506127de565b5085925050509392505050565b60006080820190506128356000830189611dbc565b6128426020830188612292565b81810360408301526128558186886125d8565b9050818103606083015261286a8184866127c3565b9050979650505050505050565b60006020828403121561288d5761288c6119e9565b5b600061289b848285016126af565b91505092915050565b600081356128b1816121ed565b80915050919050565b60008160001b9050919050565b600060ff6128d4846128ba565b9350801983169250808416831791505092915050565b60006129056129006128fb84611ae4565b611880565b611ae4565b9050919050565b6000819050919050565b61291f826128ea565b61293261292b8261290c565b83546128c7565b8255505050565b6000813561294681612655565b80915050919050565b60008160081b9050919050565b600063ffffff0061296c8461294f565b9350801983169250808416831791505092915050565b600061299d61299861299384611bf9565b611880565b611bf9565b9050919050565b6000819050919050565b6129b782612982565b6129ca6129c3826129a4565b835461295c565b8255505050565b600081356129de81612698565b80915050919050565b60008160201b9050919050565b600067ffffffff00000000612a08846129e7565b9350801983169250808416831791505092915050565b6000612a39612a34612a2f84611c17565b611880565b611c17565b9050919050565b6000819050919050565b612a5382612a1e565b612a66612a5f82612a40565b83546129f4565b8255505050565b60008135612a7a816126db565b80915050919050565b60008160401b9050919050565b600077ffffffffffffffffffffffffffffffff0000000000000000612ab484612a83565b9350801983169250808416831791505092915050565b6000612ae5612ae0612adb84611c36565b611880565b611c36565b9050919050565b6000819050919050565b612aff82612aca565b612b12612b0b82612aec565b8354612a90565b8255505050565b600081016000830180612b2b816128a4565b9050612b378184612916565b505050600081016020830180612b4c81612939565b9050612b5881846129ae565b505050600081016040830180612b6d816129d1565b9050612b798184612a4a565b505050600081016060830180612b8e81612a6d565b9050612b9a8184612af6565b5050505050565b612bab8282612b19565b5050565b600081905092915050565b6000612bc58261192e565b612bcf8185612baf565b9350612bdf81856020860161194a565b80840191505092915050565b6000819050919050565b612c06612c01826118fa565b612beb565b82525050565b6000612c188285612bba565b9150612c248284612bf5565b6020820191508190509392505050565b6000608082019050612c496000830187611904565b612c566020830186611af1565b612c636040830185611904565b612c706060830184611904565b9594505050505056fea26469706673582212204e20478e2e3070a20aa83127753a448e1b78b26fd4b44673d2f1b4027a2cf6be64736f6c634300080d0033", @@ -858,12 +858,12 @@ "storageLayout": { "storage": [ { - "astId": 4270, + "astId": 4239, "contract": "contracts/onChainFeeds/UmbrellaFeeds.sol:UmbrellaFeeds", "label": "_prices", "offset": 0, "slot": "0", - "type": "t_mapping(t_bytes32,t_struct(PriceData)3396_storage)" + "type": "t_mapping(t_bytes32,t_struct(PriceData)3365_storage)" } ], "types": { @@ -872,19 +872,19 @@ "label": "bytes32", "numberOfBytes": "32" }, - "t_mapping(t_bytes32,t_struct(PriceData)3396_storage)": { + "t_mapping(t_bytes32,t_struct(PriceData)3365_storage)": { "encoding": "mapping", "key": "t_bytes32", "label": "mapping(bytes32 => struct IUmbrellaFeeds.PriceData)", "numberOfBytes": "32", - "value": "t_struct(PriceData)3396_storage" + "value": "t_struct(PriceData)3365_storage" }, - "t_struct(PriceData)3396_storage": { + "t_struct(PriceData)3365_storage": { "encoding": "inplace", "label": "struct IUmbrellaFeeds.PriceData", "members": [ { - "astId": 3386, + "astId": 3355, "contract": "contracts/onChainFeeds/UmbrellaFeeds.sol:UmbrellaFeeds", "label": "data", "offset": 0, @@ -892,7 +892,7 @@ "type": "t_uint8" }, { - "astId": 3389, + "astId": 3358, "contract": "contracts/onChainFeeds/UmbrellaFeeds.sol:UmbrellaFeeds", "label": "heartbeat", "offset": 1, @@ -900,7 +900,7 @@ "type": "t_uint24" }, { - "astId": 3392, + "astId": 3361, "contract": "contracts/onChainFeeds/UmbrellaFeeds.sol:UmbrellaFeeds", "label": "timestamp", "offset": 4, @@ -908,7 +908,7 @@ "type": "t_uint32" }, { - "astId": 3395, + "astId": 3364, "contract": "contracts/onChainFeeds/UmbrellaFeeds.sol:UmbrellaFeeds", "label": "price", "offset": 8, diff --git a/deployments/base_production/solcInputs/dc68422c0ad35a4fe46d461b096b9383.json b/deployments/base_production/solcInputs/dc68422c0ad35a4fe46d461b096b9383.json new file mode 100644 index 00000000..43238985 --- /dev/null +++ b/deployments/base_production/solcInputs/dc68422c0ad35a4fe46d461b096b9383.json @@ -0,0 +1,125 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n }\n _balances[to] += amount;\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n _balances[account] += amount;\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n }\n _totalSupply -= amount;\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Trees proofs.\n *\n * The proofs can be generated using the JavaScript library\n * https://github.com/miguelmota/merkletreejs[merkletreejs].\n * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.\n *\n * See `test/utils/cryptography/MerkleProof.test.js` for some examples.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(\n bytes32[] memory proof,\n bytes32 root,\n bytes32 leaf\n ) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n bytes32 proofElement = proof[i];\n if (computedHash <= proofElement) {\n // Hash(current computed hash + current element of the proof)\n computedHash = _efficientHash(computedHash, proofElement);\n } else {\n // Hash(current element of the proof + current computed hash)\n computedHash = _efficientHash(proofElement, computedHash);\n }\n }\n return computedHash;\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "@umb-network/toolbox/dist/contracts/lib/ValueDecoder.sol": { + "content": "//SPDX-License-Identifier: Unlicensed\npragma solidity >=0.6.8;\n\nlibrary ValueDecoder {\n function toUint(bytes memory _bytes) internal pure returns (uint256 value) {\n assembly {\n value := mload(add(_bytes, 32))\n }\n }\n\n function toUint(bytes32 _bytes) internal pure returns (uint256 value) {\n assembly {\n value := _bytes\n }\n }\n\n function toInt(uint224 u) internal pure returns (int256) {\n int224 i;\n uint224 max = type(uint224).max;\n\n if (u <= (max - 1) / 2) { // positive values\n assembly {\n i := add(u, 0)\n }\n\n return i;\n } else { // negative values\n assembly {\n i := sub(sub(u, max), 1)\n }\n }\n\n return i;\n }\n}\n\n" + }, + "contracts/BaseChain.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\";\nimport \"@umb-network/toolbox/dist/contracts/lib/ValueDecoder.sol\";\n\nimport \"./interfaces/IBaseChainV1.sol\";\nimport \"./interfaces/IStakingBank.sol\";\nimport \"./extensions/Registrable.sol\";\nimport \"./Registry.sol\";\n\nabstract contract BaseChain is Registrable, Ownable {\n using ValueDecoder for bytes;\n using ValueDecoder for uint224;\n using MerkleProof for bytes32[];\n\n /// @param root merkle root for consensus\n /// @param dataTimestamp consensus timestamp\n struct Block {\n bytes32 root;\n uint32 dataTimestamp;\n }\n\n /// @param value FCD value\n /// @param dataTimestamp FCD timestamp\n struct FirstClassData {\n uint224 value;\n uint32 dataTimestamp;\n }\n\n /// @param blocksCountOffset number of all blocks that were generated before switching to this contract\n /// @param sequence is a total number of blocks (consensus rounds) including previous contracts\n /// @param lastTimestamp is a timestamp of last submitted block\n /// @param padding number of seconds that need to pass before new submit will be possible\n /// @param deprecated flag that changes to TRUE on `unregister`, when TRUE submissions are not longer available\n struct ConsensusData {\n uint32 blocksCountOffset;\n uint32 sequence;\n uint32 lastTimestamp;\n uint32 padding;\n bool deprecated;\n }\n\n uint256 constant public VERSION = 2;\n\n bool internal immutable _ALLOW_FOR_MIXED_TYPE; // solhint-disable-line var-name-mixedcase\n\n bytes4 constant private _VERSION_SELECTOR = bytes4(keccak256(\"VERSION()\"));\n\n /// @dev minimal number of signatures required for accepting submission (PoA)\n uint16 internal immutable _REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\n\n ConsensusData internal _consensusData;\n\n bytes constant public ETH_PREFIX = \"\\x19Ethereum Signed Message:\\n32\";\n\n /// @dev block id (consensus ID) => root\n /// consensus ID is at the same time consensus timestamp\n mapping(uint256 => bytes32) public roots;\n\n /// @dev FCD key => FCD data\n mapping(bytes32 => FirstClassData) public fcds;\n\n event LogDeprecation(address indexed deprecator);\n event LogPadding(address indexed executor, uint32 timePadding);\n\n error ArraysDataDoNotMatch();\n error AlreadyDeprecated();\n error AlreadyRegistered();\n error BlockSubmittedToFastOrDataToOld();\n error ContractNotReady();\n error FCDOverflow();\n error InvalidContractType();\n error NoChangeToState();\n error OnlyOwnerOrRegistry();\n error UnregisterFirst();\n\n modifier onlyOwnerOrRegistry () {\n if (msg.sender != address(contractRegistry) && msg.sender != owner()) revert OnlyOwnerOrRegistry();\n _;\n }\n\n /// @param _contractRegistry Registry address\n /// @param _padding required \"space\" between blocks in seconds\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n constructor(\n IRegistry _contractRegistry,\n uint32 _padding,\n uint16 _requiredSignatures,\n bool _allowForMixedType\n ) Registrable(_contractRegistry) {\n _ALLOW_FOR_MIXED_TYPE = _allowForMixedType;\n _REQUIRED_SIGNATURES = _requiredSignatures;\n\n _setPadding(_padding);\n\n BaseChain oldChain = BaseChain(_contractRegistry.getAddress(\"Chain\"));\n\n if (address(oldChain) == address(0)) {\n // if this is first contract in sidechain, then we need to initialise lastTimestamp so submission\n // can be possible\n _consensusData.lastTimestamp = uint32(block.timestamp) - _padding - 1;\n }\n }\n\n /// @dev setter for `padding`\n function setPadding(uint16 _padding) external {\n _setPadding(_padding);\n }\n\n /// @notice if this method needs to be called manually (not from Registry)\n /// it is important to do it as part of tx batch\n /// eg using multisig, we should prepare set of transactions and confirm them all at once\n /// @inheritdoc Registrable\n function register() external override onlyOwnerOrRegistry {\n address oldChain = contractRegistry.getAddress(\"Chain\");\n\n // registration must be done before address in registry is replaced\n if (oldChain == address(this)) revert AlreadyRegistered();\n\n if (oldChain == address(0x0)) {\n return;\n }\n\n _cloneLastDataFromPrevChain(oldChain);\n }\n\n /// @inheritdoc Registrable\n function unregister() external override onlyOwnerOrRegistry {\n // in case we deprecated contract manually, we simply return\n if (_consensusData.deprecated) return;\n\n address newChain = contractRegistry.getAddress(\"Chain\");\n // unregistering must be done after address in registry is replaced\n if (newChain == address(this)) revert UnregisterFirst();\n\n // TODO:\n // I think we need to remove restriction for type (at least once)\n // when we will switch to multichain architecture\n\n if (!_ALLOW_FOR_MIXED_TYPE) {\n // can not be replaced with chain of different type\n if (BaseChain(newChain).isForeign() != this.isForeign()) revert InvalidContractType();\n }\n\n _consensusData.deprecated = true;\n emit LogDeprecation(msg.sender);\n }\n\n /// @notice it allows to deprecate contract manually\n /// Only new Registry calls `unregister()` where we set deprecated to true\n /// In old Registries we don't have this feature, so in order to safely redeploy new Chain\n /// we will have to first deprecate current contract manually, then register new contract\n function deprecate() external onlyOwnerOrRegistry {\n if (_consensusData.deprecated) revert AlreadyDeprecated();\n\n _consensusData.deprecated = true;\n emit LogDeprecation(msg.sender);\n }\n\n /// @dev getter for `_consensusData`\n function getConsensusData() external view returns (ConsensusData memory) {\n return _consensusData;\n }\n\n /// @dev number of blocks (consensus rounds) saved in this contract\n function blocksCount() external view returns (uint256) {\n return _consensusData.sequence - _consensusData.blocksCountOffset;\n }\n\n function blocksCountOffset() external view returns (uint32) {\n return _consensusData.blocksCountOffset;\n }\n\n function lastBlockId() external view returns (uint256) {\n return _consensusData.lastTimestamp;\n }\n\n /// @return TRUE if contract is ForeignChain, FALSE otherwise\n function isForeign() external pure virtual returns (bool);\n\n /// @inheritdoc Registrable\n function getName() external pure override returns (bytes32) {\n return \"Chain\";\n }\n\n /// @param _affidavit root and FCDs hashed together\n /// @param _v part of signature\n /// @param _r part of signature\n /// @param _s part of signature\n /// @return signer address\n function recoverSigner(bytes32 _affidavit, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _affidavit));\n return ecrecover(hash, _v, _r, _s);\n }\n\n /// @param _blockId ID of submitted block\n /// @return block data (root + timestamp)\n function blocks(uint256 _blockId) external view returns (Block memory) {\n return Block(roots[_blockId], uint32(_blockId));\n }\n\n /// @return current block ID\n /// please note, that current ID is not the same as last ID, current means that once padding pass,\n /// ID will switch to next one and it will be pointing to empty submit until submit for that ID is done\n function getBlockId() external view returns (uint32) {\n if (_consensusData.lastTimestamp == 0) return 0;\n\n return getBlockIdAtTimestamp(block.timestamp);\n }\n\n function requiredSignatures() external view returns (uint16) {\n return _REQUIRED_SIGNATURES;\n }\n\n /// @dev calculates block ID for provided timestamp\n /// this function does not works for past timestamps\n /// @param _timestamp current or future timestamp\n /// @return block ID for provided timestamp\n function getBlockIdAtTimestamp(uint256 _timestamp) virtual public view returns (uint32) {\n ConsensusData memory data = _consensusData;\n\n unchecked {\n // we can't overflow because we adding two `uint32`\n if (data.lastTimestamp + data.padding < _timestamp) {\n return uint32(_timestamp);\n }\n }\n\n return data.lastTimestamp;\n }\n\n /// @return last submitted block ID, please note, that on deployment, when there is no submission for this contract\n /// block for last ID will be available in previous contract\n function getLatestBlockId() virtual public view returns (uint32) {\n return _consensusData.lastTimestamp;\n }\n\n /// @dev verifies if the leaf is valid leaf for merkle tree\n /// @param _proof merkle proof for merkle tree\n /// @param _root merkle root\n /// @param _leaf leaf hash\n /// @return TRUE if `_leaf` is valid, FALSE otherwise\n function verifyProof(bytes32[] memory _proof, bytes32 _root, bytes32 _leaf) public pure returns (bool) {\n if (_root == bytes32(0)) {\n return false;\n }\n\n return _proof.verify(_root, _leaf);\n }\n\n /// @dev creates leaf hash, that has is used in merkle tree\n /// @param _key key under which we store the value\n /// @param _value value itself as bytes\n /// @return leaf hash\n function hashLeaf(bytes memory _key, bytes memory _value) public pure returns (bytes32) {\n return keccak256(abi.encodePacked(_key, _value));\n }\n\n /// @dev verifies, if provided key-value pair was part of consensus\n /// @param _blockId consensus ID for which we doing a check\n /// @param _proof merkle proof for pair\n /// @param _key pair key\n /// @param _value pair value\n /// @return TRUE if key-value par was part of consensus, FALSE otherwise\n function verifyProofForBlock(\n uint256 _blockId,\n bytes32[] memory _proof,\n bytes memory _key,\n bytes memory _value\n )\n public\n view\n returns (bool)\n {\n return _proof.verify(roots[_blockId], keccak256(abi.encodePacked(_key, _value)));\n }\n\n /// @dev this is helper method, that extracts one merkle proof from many hashed provided as bytes\n /// @param _data many hashes as bytes\n /// @param _offset this is starting point for extraction\n /// @param _items how many hashes to extract\n /// @return merkle proof (array of bytes32 hashes)\n function bytesToBytes32Array(\n bytes memory _data,\n uint256 _offset,\n uint256 _items\n )\n public\n pure\n returns (bytes32[] memory)\n {\n bytes32[] memory dataList = new bytes32[](_items);\n\n // we can unchecked because we working only with `i` and `_offset`\n // in case of wrong `_offset` it will throw\n unchecked {\n for (uint256 i = 0; i < _items; i++) {\n bytes32 temp;\n uint256 idx = (i + 1 + _offset) * 32;\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n temp := mload(add(_data, idx))\n }\n\n dataList[i] = temp;\n }\n }\n\n return (dataList);\n }\n\n /// @dev batch method for data verification\n /// @param _blockIds consensus IDs for which we doing a checks\n /// @param _proofs merkle proofs for all pair, sequence of hashes provided as bytes\n /// @param _proofItemsCounter array of counters, each counter tells how many hashes proof for each leaf has\n /// @param _leaves array of merkle leaves\n /// @return results array of verification results, TRUE if leaf is part of consensus, FALSE otherwise\n function verifyProofs(\n uint32[] memory _blockIds,\n bytes memory _proofs,\n uint256[] memory _proofItemsCounter,\n bytes32[] memory _leaves\n )\n public\n view\n returns (bool[] memory results)\n {\n results = new bool[](_leaves.length);\n uint256 offset = 0;\n\n for (uint256 i = 0; i < _leaves.length;) {\n results[i] = bytesToBytes32Array(_proofs, offset, _proofItemsCounter[i]).verify(\n roots[_blockIds[i]], _leaves[i]\n );\n\n unchecked {\n // we can uncheck because it will not overflow in a lifetime, and if someone provide invalid counter\n // we verification will not be valid (or we throw because of invalid memory access)\n offset += _proofItemsCounter[i];\n // we can uncheck because `i` will not overflow in a lifetime\n i++;\n }\n }\n }\n\n /// @param _blockId consensus ID\n /// @return root for provided consensus ID\n function getBlockRoot(uint32 _blockId) external view returns (bytes32) {\n return roots[_blockId];\n }\n\n /// @param _blockId consensus ID\n /// @return timestamp for provided consensus ID\n function getBlockTimestamp(uint32 _blockId) external view returns (uint32) {\n return roots[_blockId] == bytes32(0) ? 0 : _blockId;\n }\n\n /// @dev batch getter for FCDs\n /// @param _keys FCDs keys to fetch\n /// @return values array of FCDs values\n /// @return timestamps array of FCDs timestamps\n function getCurrentValues(bytes32[] calldata _keys)\n external\n view\n returns (uint256[] memory values, uint32[] memory timestamps)\n {\n timestamps = new uint32[](_keys.length);\n values = new uint256[](_keys.length);\n\n for (uint i=0; i<_keys.length;) {\n FirstClassData storage numericFCD = fcds[_keys[i]];\n values[i] = uint256(numericFCD.value);\n timestamps[i] = numericFCD.dataTimestamp;\n\n unchecked {\n // we can uncheck because `i` will not overflow in a lifetime\n i++;\n }\n }\n }\n\n /// @dev getter for single FCD value\n /// @param _key FCD key\n /// @return value FCD value\n /// @return timestamp FCD timestamp\n function getCurrentValue(bytes32 _key) external view returns (uint256 value, uint256 timestamp) {\n FirstClassData storage numericFCD = fcds[_key];\n return (uint256(numericFCD.value), numericFCD.dataTimestamp);\n }\n\n /// @dev getter for single FCD value in case its type is `int`\n /// @param _key FCD key\n /// @return value FCD value\n /// @return timestamp FCD timestamp\n function getCurrentIntValue(bytes32 _key) external view returns (int256 value, uint256 timestamp) {\n FirstClassData storage numericFCD = fcds[_key];\n return (numericFCD.value.toInt(), numericFCD.dataTimestamp);\n }\n\n function _setPadding(uint32 _padding) internal onlyOwner {\n if (_consensusData.padding == _padding) revert NoChangeToState();\n\n _consensusData.padding = _padding;\n emit LogPadding(msg.sender, _padding);\n }\n\n /// @dev we cloning last block time, because we will need reference point for next submissions\n function _cloneLastDataFromPrevChain(address _prevChain) internal {\n (bool success, bytes memory v) = _prevChain.staticcall(abi.encode(_VERSION_SELECTOR));\n uint256 prevVersion = success ? abi.decode(v, (uint256)) : 1;\n\n if (prevVersion == 1) {\n uint32 latestId = IBaseChainV1(address(_prevChain)).getLatestBlockId();\n _consensusData.lastTimestamp = IBaseChainV1(address(_prevChain)).getBlockTimestamp(latestId);\n\n // +1 because getLatestBlockId subtracts 1\n // +1 because it might be situation when tx is already in progress in old contract\n // and old contract do not have deprecated flag\n _consensusData.sequence = latestId + 2;\n _consensusData.blocksCountOffset = latestId + 2;\n } else { // VERSION 2\n // with new Registry, we have register/unregister methods\n // Chain will be deprecated, so there is no need to do \"+1\" as in old version\n // TODO what with current Registries??\n // we need a way to make it deprecated!\n ConsensusData memory data = BaseChain(_prevChain).getConsensusData();\n\n _consensusData.sequence = data.sequence;\n _consensusData.blocksCountOffset = data.sequence;\n _consensusData.lastTimestamp = data.lastTimestamp;\n }\n }\n}\n" + }, + "contracts/Chain.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./BaseChain.sol\";\n\ncontract Chain is BaseChain {\n IStakingBank public immutable stakingBank;\n\n event LogMint(address indexed minter, uint256 blockId, uint256 staked, uint256 power);\n event LogVoter(uint256 indexed blockId, address indexed voter, uint256 vote);\n\n error NotEnoughSignatures();\n error SignaturesOutOfOrder();\n\n /// @param _contractRegistry Registry address\n /// @param _padding required \"space\" between blocks in seconds\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n /// @param _allowForMixedType we have two \"types\" of Chain: HomeChain and ForeignChain, when we redeploying\n /// we don't want to mix up them, so we checking, if new Chain has the same type as current one.\n /// However, when we will be switching from one homechain to another one, we have to allow for this mixing up.\n /// This flag will tell contract, if this is the case.\n constructor(\n IRegistry _contractRegistry,\n uint32 _padding,\n uint16 _requiredSignatures,\n bool _allowForMixedType\n ) BaseChain(_contractRegistry, _padding, _requiredSignatures, _allowForMixedType) {\n stakingBank = IStakingBank(_contractRegistry.requireAndGetAddress(\"StakingBank\"));\n }\n\n /// @dev method for submitting consensus data\n /// @param _dataTimestamp consensus timestamp, this is time for all data in merkle tree including FCDs\n /// @param _root merkle root\n /// @param _keys FCDs keys\n /// @param _values FCDs values\n /// @param _v array of `v` part of validators signatures\n /// @param _r array of `r` part of validators signatures\n /// @param _s array of `s` part of validators signatures\n // solhint-disable-next-line function-max-lines, code-complexity\n function submit(\n uint32 _dataTimestamp,\n bytes32 _root,\n bytes32[] memory _keys,\n uint256[] memory _values,\n uint8[] memory _v,\n bytes32[] memory _r,\n bytes32[] memory _s\n ) external {\n // below two checks are only for pretty errors, so we can safe gas and allow for raw revert\n // if (_keys.length != _values.length) revert ArraysDataDoNotMatch();\n // if (_v.length != _r.length || _r.length != _s.length) revert ArraysDataDoNotMatch();\n\n _verifySubmitTimestampAndIncSequence(_dataTimestamp);\n\n // we can't expect minter will have exactly the same timestamp\n // but for sure we can demand not to be off by a lot, that's why +3sec\n // temporary remove this condition, because recently on ropsten we see cases when minter/node\n // can be even 100sec behind\n // require(_dataTimestamp <= block.timestamp + 3,\n // string(abi.encodePacked(\"oh, so you can predict the future:\", _dataTimestamp - block.timestamp + 48)));\n\n bytes memory testimony = abi.encodePacked(_dataTimestamp, _root);\n\n for (uint256 i = 0; i < _keys.length;) {\n if (uint224(_values[i]) != _values[i]) revert FCDOverflow();\n\n fcds[_keys[i]] = FirstClassData(uint224(_values[i]), _dataTimestamp);\n testimony = abi.encodePacked(testimony, _keys[i], _values[i]);\n\n unchecked {\n // we can't pass enough data to overflow\n i++;\n }\n }\n\n uint256 signatures = 0;\n uint256 power = 0;\n //uint256 staked = stakingBank.totalSupply();\n bytes32 affidavit = keccak256(testimony);\n\n address prevSigner = address(0x0);\n\n for (uint256 i; i < _v.length;) {\n address signer = recoverSigner(affidavit, _v[i], _r[i], _s[i]);\n uint256 balance = stakingBank.balanceOf(signer);\n\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\n\n prevSigner = signer;\n\n if (balance == 0) {\n unchecked { i++; }\n continue;\n }\n\n signatures++;\n emit LogVoter(uint256(_dataTimestamp), signer, balance);\n\n unchecked {\n // we can't overflow because that means token overflowed\n // and even if we do, we will get lower power\n power += balance;\n i++;\n }\n }\n\n if (signatures < _REQUIRED_SIGNATURES) revert NotEnoughSignatures();\n\n emit LogMint(msg.sender, _dataTimestamp, stakingBank.totalSupply(), power);\n\n // TODO remember to protect against flash loans when DPoS will be in place\n // we turn on power once we have DPoS in action, we have PoA now\n // require(power * 100 / staked >= 66, \"not enough power was gathered\");\n\n roots[_dataTimestamp] = _root;\n _consensusData.lastTimestamp = _dataTimestamp;\n }\n\n /// @inheritdoc BaseChain\n function isForeign() external pure virtual override returns (bool) {\n return false;\n }\n\n /// @dev helper method that returns all important data about current state of contract\n /// @return blockNumber `block.number`\n /// @return timePadding `this.padding`\n /// @return lastDataTimestamp timestamp for last submitted consensus\n /// @return lastId ID of last submitted consensus\n /// @return nextLeader leader for `block.timestamp + 1`\n /// @return nextBlockId block ID for `block.timestamp + padding`\n /// @return validators array of all validators addresses\n /// @return powers array of all validators powers\n /// @return locations array of all validators locations\n /// @return staked total UMB staked by validators\n /// @return minSignatures `this.requiredSignatures`\n function getStatus() external view virtual returns(\n uint256 blockNumber,\n uint32 timePadding,\n uint32 lastDataTimestamp,\n uint32 lastId,\n address nextLeader,\n uint32 nextBlockId,\n address[] memory validators,\n uint256[] memory powers,\n string[] memory locations,\n uint256 staked,\n uint16 minSignatures\n ) {\n ConsensusData memory data = _consensusData;\n\n blockNumber = block.number;\n timePadding = data.padding;\n lastId = data.lastTimestamp;\n lastDataTimestamp = lastId;\n minSignatures = _REQUIRED_SIGNATURES;\n\n staked = stakingBank.totalSupply();\n uint256 numberOfValidators = stakingBank.getNumberOfValidators();\n powers = new uint256[](numberOfValidators);\n validators = new address[](numberOfValidators);\n locations = new string[](numberOfValidators);\n\n for (uint256 i = 0; i < numberOfValidators;) {\n validators[i] = stakingBank.addresses(i);\n (, locations[i]) = stakingBank.validators(validators[i]);\n powers[i] = stakingBank.balanceOf(validators[i]);\n\n unchecked {\n // we will run out of gas before overflow happen\n i++;\n }\n }\n\n unchecked {\n // we will not overflow with timestamp in a lifetime\n nextBlockId = lastId + data.padding + 1;\n\n nextLeader = numberOfValidators > 0\n // we will not overflow with timestamp in a lifetime\n ? validators[getLeaderIndex(numberOfValidators, block.timestamp + 1)]\n : address(0);\n }\n }\n\n /// @return address of leader for next second\n function getNextLeaderAddress() external view returns (address) {\n return getLeaderAddressAtTime(block.timestamp + 1);\n }\n\n /// @return address of current leader\n function getLeaderAddress() external view returns (address) {\n return getLeaderAddressAtTime(block.timestamp);\n }\n\n /// @param _numberOfValidators total number of validators\n /// @param _timestamp timestamp for which you want to calculate index\n /// @return leader index, use it for StakingBank.addresses[index] to fetch leader address\n function getLeaderIndex(uint256 _numberOfValidators, uint256 _timestamp) public view virtual returns (uint256) {\n ConsensusData memory data = _consensusData;\n\n unchecked {\n // we will not overflow on `timestamp` and `padding` in a life time\n // timePadding + 1 => because padding is a space between blocks,\n // so next round starts on first block after padding\n // TODO will it work for off-chain??\n uint256 validatorIndex = data.sequence + (_timestamp - data.lastTimestamp) / (data.padding + 1);\n\n return validatorIndex % _numberOfValidators;\n }\n }\n\n // @todo - properly handled non-enabled validators, newly added validators, and validators with low stake\n /// @param _timestamp timestamp for which you want to calculate leader address\n /// @return leader address for provider timestamp\n function getLeaderAddressAtTime(uint256 _timestamp) public view virtual returns (address) {\n uint256 numberOfValidators = stakingBank.getNumberOfValidators();\n\n if (numberOfValidators == 0) {\n return address(0x0);\n }\n\n uint256 validatorIndex = getLeaderIndex(numberOfValidators, _timestamp);\n\n return stakingBank.addresses(validatorIndex);\n }\n\n /// @dev we had stack too deep in `submit` so this method was created as a solution\n // we increasing `_consensusData.sequence` here so we don't have to read sequence again in other place\n function _verifySubmitTimestampAndIncSequence(uint256 _dataTimestamp) internal {\n ConsensusData memory data = _consensusData;\n\n // `data.lastTimestamp` must be setup either on deployment\n // or via cloning from previous contract\n if (data.lastTimestamp == 0) revert ContractNotReady();\n\n unchecked {\n // we will not overflow with timestamp and padding in a life time\n if (data.lastTimestamp + data.padding >= _dataTimestamp) revert BlockSubmittedToFastOrDataToOld();\n }\n\n unchecked {\n // we will not overflow in a life time\n _consensusData.sequence = uint32(data.sequence + 1);\n }\n }\n}\n" + }, + "contracts/extensions/Registrable.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\n/// @dev Any contract that we want to register in ContractRegistry, must inherit from Registrable\nabstract contract Registrable {\n IRegistry public immutable contractRegistry;\n\n modifier onlyFromContract(address _msgSender, bytes32 _contractName) {\n require(\n contractRegistry.getAddress(_contractName) == _msgSender,\n string(abi.encodePacked(\"caller is not \", _contractName))\n );\n _;\n }\n\n modifier withRegistrySetUp() {\n require(address(contractRegistry) != address(0x0), \"_registry is empty\");\n _;\n }\n\n constructor(IRegistry _contractRegistry) {\n require(address(_contractRegistry) != address(0x0), \"_registry is empty\");\n contractRegistry = _contractRegistry;\n }\n\n /// @dev this method will be called as a first method in registration process when old contract will be replaced\n /// when called, old contract address is still in registry\n function register() virtual external;\n\n /// @dev this method will be called as a last method in registration process when old contract will be replaced\n /// when called, new contract address is already in registry\n function unregister() virtual external;\n\n /// @return contract name as bytes32\n function getName() virtual external pure returns (bytes32);\n\n /// @dev helper method for fetching StakingBank address\n function stakingBankContract() public view returns (IStakingBank) {\n return IStakingBank(contractRegistry.requireAndGetAddress(\"StakingBank\"));\n }\n\n /// @dev helper method for fetching UMB address\n function tokenContract() public view withRegistrySetUp returns (ERC20) {\n return ERC20(contractRegistry.requireAndGetAddress(\"UMB\"));\n }\n}\n" + }, + "contracts/ForeignChain.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./Chain.sol\";\n\n/// @dev contract for foreign chains\ncontract ForeignChain is Chain {\n error NotSupported();\n\n /// @param _contractRegistry Registry address\n /// @param _padding required \"space\" between blocks in seconds\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n constructor(\n IRegistry _contractRegistry,\n uint32 _padding,\n uint16 _requiredSignatures,\n bool _allowForMixedType\n ) Chain(_contractRegistry, _padding, _requiredSignatures, _allowForMixedType) {\n // no additional configuration needed\n }\n\n /// @inheritdoc BaseChain\n function isForeign() external pure override returns (bool) {\n return true;\n }\n\n /// @inheritdoc Chain\n /// @notice this method is made to be compatible with MasterChain, but it does not return full data eg validators\n /// data will be missing.\n /// @return blockNumber `block.number`\n /// @return timePadding `this.padding`\n /// @return lastDataTimestamp timestamp for last submitted consensus\n /// @return lastId ID of last submitted consensus\n /// @return nextLeader will be always address(0)\n /// @return nextBlockId block ID for `block.timestamp + padding`\n /// @return validators array will be always empty\n /// @return powers array will be always empty\n /// @return locations array will be always empty\n /// @return staked total UMB staked by validators\n /// @return minSignatures `this.requiredSignatures`\n function getStatus() external view override returns(\n uint256 blockNumber,\n uint32 timePadding,\n uint32 lastDataTimestamp,\n uint32 lastId,\n address nextLeader,\n uint32 nextBlockId,\n address[] memory validators,\n uint256[] memory powers,\n string[] memory locations,\n uint256 staked,\n uint16 minSignatures\n ) {\n ConsensusData memory data = _consensusData;\n\n blockNumber = block.number;\n timePadding = data.padding;\n lastId = data.lastTimestamp;\n lastDataTimestamp = lastId;\n minSignatures = _REQUIRED_SIGNATURES;\n\n staked = stakingBank.totalSupply();\n uint256 numberOfValidators = 0;\n powers = new uint256[](numberOfValidators);\n validators = new address[](numberOfValidators);\n locations = new string[](numberOfValidators);\n nextLeader = address(0);\n\n unchecked {\n // we will not overflow with timestamp in a lifetime\n nextBlockId = lastId + data.padding + 1;\n }\n }\n\n function getLeaderIndex(uint256, uint256) public pure override returns (uint256) {\n revert NotSupported();\n }\n\n function getLeaderAddressAtTime(uint256) public pure override returns (address) {\n revert NotSupported();\n }\n}\n" + }, + "contracts/interfaces/IBaseChainV1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IBaseChainV1 {\n /// @dev number of blocks (consensus rounds) saved in this contract\n function blocksCount() external returns (uint32);\n\n /// @dev number of all blocks that were generated before switching to this contract\n /// please note, that there might be a gap of one block when we switching from old to new contract\n /// see constructor for details\n function blocksCountOffset() external returns (uint32);\n\n function getLatestBlockId() external view returns (uint32);\n\n function getBlockTimestamp(uint32 _blockId) external view returns (uint32);\n\n function getStatus() external view returns (\n uint256 blockNumber,\n uint16 timePadding,\n uint32 lastDataTimestamp,\n uint32 lastId,\n uint32 nextBlockId\n );\n}\n" + }, + "contracts/interfaces/IRegistry.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\n\ninterface IRegistry {\n event LogRegistered(address indexed destination, bytes32 name);\n\n /// @dev imports new contract addresses and override old addresses, if they exist under provided name\n /// This method can be used for contracts that for some reason do not have `getName` method\n /// @param _names array of contract names that we want to register\n /// @param _destinations array of contract addresses\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external;\n\n /// @dev imports new contracts and override old addresses, if they exist.\n /// Names of contracts are fetched directly from each contract by calling `getName`\n /// @param _destinations array of contract addresses\n function importContracts(address[] calldata _destinations) external;\n\n /// @dev this method ensure, that old and new contract is aware of it state in registry\n /// Note: BSC registry does not have this method. This method was introduced in later stage.\n /// @param _newContract address of contract that will replace old one\n function atomicUpdate(address _newContract) external;\n\n /// @dev similar to `getAddress` but throws when contract name not exists\n /// @param name contract name\n /// @return contract address registered under provided name or throws, if does not exists\n function requireAndGetAddress(bytes32 name) external view returns (address);\n\n /// @param name contract name in a form of bytes32\n /// @return contract address registered under provided name\n function getAddress(bytes32 name) external view returns (address);\n\n /// @param _name contract name\n /// @return contract address assigned to the name or address(0) if not exists\n function getAddressByString(string memory _name) external view returns (address);\n\n /// @dev helper method that converts string to bytes32,\n /// you can use to to generate contract name\n function stringToBytes32(string memory _string) external pure returns (bytes32 result);\n}\n" + }, + "contracts/interfaces/IStakingBank.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IStakingBank is IERC20 {\n /// @param id address of validator wallet\n /// @param location URL of the validator API\n struct Validator {\n address id;\n string location;\n }\n\n event LogValidatorRegistered(address indexed id);\n event LogValidatorUpdated(address indexed id);\n event LogValidatorRemoved(address indexed id);\n event LogMinAmountForStake(uint256 minAmountForStake);\n\n /// @dev setter for `minAmountForStake`\n function setMinAmountForStake(uint256 _minAmountForStake) external;\n\n /// @dev allows to stake `token` by validators\n /// Validator needs to approve StakingBank beforehand\n /// @param _value amount of tokens to stake\n function stake(uint256 _value) external;\n\n /// @dev notification about approval from `_from` address on UMB token\n /// Staking bank will stake max approved amount from `_from` address\n /// @param _from address which approved token spend for IStakingBank\n function receiveApproval(address _from) external returns (bool success);\n\n /// @dev withdraws stake tokens\n /// it throws, when balance will be less than required minimum for stake\n /// to withdraw all use `exit`\n function withdraw(uint256 _value) external returns (bool success);\n\n /// @dev unstake and withdraw all tokens\n function exit() external returns (bool success);\n\n /// @dev creates (register) new validator\n /// @param _id validator address\n /// @param _location location URL of the validator API\n function create(address _id, string calldata _location) external;\n\n /// @dev removes validator\n /// @param _id validator wallet\n function remove(address _id) external;\n\n /// @dev updates validator location\n /// @param _id validator wallet\n /// @param _location new validator URL\n function update(address _id, string calldata _location) external;\n\n /// @return total number of registered validators (with and without balance)\n function getNumberOfValidators() external view returns (uint256);\n\n /// @dev gets validator address for provided index\n /// @param _ix index in array of list of all validators wallets\n function addresses(uint256 _ix) external view returns (address);\n\n /// @param _id address of validator\n /// @return id address of validator\n /// @return location URL of validator\n function validators(address _id) external view returns (address id, string memory location);\n}\n" + }, + "contracts/interfaces/IStakingBankStatic.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./IStakingBank.sol\";\n\n\ninterface IStakingBankStatic is IStakingBank {\n /// @param _validators array of validators addresses to verify\n /// @return TRUE when all validators are valid, FALSE otherwise\n function verifyValidators(address[] calldata _validators) external view returns (bool);\n}\n" + }, + "contracts/interfaces/IUmbrellaFeeds.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IUmbrellaFeeds {\n struct PriceData {\n /// @dev this is placeholder, that can be used for some additional data\n /// atm of creating this smart contract, it is only used as marker for removed data (when == type(uint8).max)\n uint8 data;\n /// @dev heartbeat: how often price data will be refreshed in case price stay flat\n uint24 heartbeat;\n /// @dev timestamp: price time, at this time validators run consensus\n uint32 timestamp;\n /// @dev price\n uint128 price;\n }\n\n struct Signature {\n uint8 v;\n bytes32 r;\n bytes32 s;\n }\n\n /// @dev method for submitting consensus data\n /// @param _priceKeys array of keys for `_priceDatas`\n /// @param _priceDatas PriceData signed by validators\n /// @param _signatures validators signatures\n function update(\n bytes32[] calldata _priceKeys,\n PriceData[] calldata _priceDatas,\n Signature[] calldata _signatures\n ) external;\n\n /// @dev it will return array of price datas for provided `_keys`\n /// In case ony of feed does not exist, fallback call will be executed for that feed.\n /// @notice If data for any key not exists, function will revert. Use `getManyPriceDataRaw` method if you don't\n /// want revert.\n /// @param _keys array of feed keys\n /// @return data PriceData array\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data);\n\n /// @dev same as getManyPriceData() but does not revert on empty data.\n /// @notice This method does no revert if some data does not exists.\n /// Check `data.timestamp` to see if price exist, if it is 0, then it does not exist.\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data);\n\n /// @dev this is main endpoint for reading feeds.\n /// In case timestamp is empty (that means there is no data), contract will revert.\n /// If you do not need whole data from `PriceData` struct, you can save some gas by using other view methods that\n /// returns just what you need.\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return data full PriceData struct\n function getPriceData(bytes32 _key) external view returns (PriceData memory data);\n\n /// @notice reader for mapping\n /// @param _key hash of feed name\n /// @return data full PriceData struct\n function prices(bytes32 _key) external view returns (PriceData memory data);\n\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return price\n function getPrice(bytes32 _key) external view returns (uint128 price);\n\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return price\n /// @return timestamp\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp);\n\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return price\n /// @return timestamp\n /// @return heartbeat\n function getPriceTimestampHeartbeat(bytes32 _key)\n external\n view\n returns (uint128 price, uint32 timestamp, uint24 heartbeat);\n\n /// @dev This method should be used only for Layer2 as it is more gas consuming than others views.\n /// @notice It does not revert on empty data.\n /// @param _name string feed name\n /// @return data PriceData\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data);\n\n /// @dev decimals for prices stored in this contract\n function DECIMALS() external view returns (uint8); // solhint-disable-line func-name-mixedcase\n}\n" + }, + "contracts/interfaces/StakingBankStaticNotSupported.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./IStakingBank.sol\";\n\nabstract contract StakingBankStaticNotSupported is IStakingBank {\n error NotSupported();\n\n function create(address, string calldata) external pure {\n revert NotSupported();\n }\n\n function update(address, string calldata) external pure {\n revert NotSupported();\n }\n\n function remove(address) external pure {\n revert NotSupported();\n }\n\n function transfer(address, uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function transferFrom(address, address, uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function receiveApproval(address) external pure returns (bool) {\n revert NotSupported();\n }\n\n function allowance(address, address) external pure returns (uint256) {\n revert NotSupported();\n }\n\n function approve(address, uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function stake(uint256) external pure {\n revert NotSupported();\n }\n\n function withdraw(uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function exit() external pure returns (bool) {\n revert NotSupported();\n }\n\n function setMinAmountForStake(uint256) external pure {\n revert NotSupported();\n }\n}\n" + }, + "contracts/mock/Distributor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport \"../Registry.sol\";\n\ncontract Distributor is Ownable {\n address[] public recipients;\n uint256 public bottomLimit = 5e17;\n uint256 public topLimit = 1e18;\n\n constructor(address[] memory _recipients) {\n recipients = _recipients;\n }\n\n receive() external payable {\n distribute();\n }\n\n function setLimits(uint256 _bottom, uint256 _top) external onlyOwner {\n bottomLimit = _bottom;\n topLimit = _top;\n }\n\n function withdraw() external {\n uint balance = address(this).balance;\n uint buffer = recipients.length * (topLimit - bottomLimit);\n\n if (balance > buffer) {\n payable(owner()).transfer(balance - buffer);\n }\n }\n\n function addRecipients(address[] calldata _recipients) external onlyOwner {\n for (uint256 i = 0; i < _recipients.length; i++) {\n recipients.push(_recipients[i]);\n }\n }\n\n function removeRecipient(address _recipient) external onlyOwner {\n for (uint256 i = 0; i < recipients.length; i++) {\n if (recipients[i] == _recipient) {\n recipients[i] = recipients[recipients.length - 1];\n recipients.pop();\n return;\n }\n }\n }\n\n function recipientsCount() external view returns (uint256) {\n return recipients.length;\n }\n\n function allRecipients() external view returns (address[] memory) {\n return recipients;\n }\n\n function getName() external pure returns (bytes32) {\n return \"Distributor\";\n }\n\n function distribute() public {\n uint256 limit = bottomLimit;\n uint256 top = topLimit;\n uint256 count = recipients.length;\n uint256 totalBalance = address(this).balance;\n\n for (uint256 i = 0; i < count; i++) {\n uint256 balance = recipients[i].balance;\n\n if (balance > limit) {\n continue;\n }\n\n uint256 amount = top - balance > totalBalance ? totalBalance : top - balance;\n\n if (amount > 0) {\n payable(recipients[i]).transfer(amount);\n totalBalance -= amount;\n }\n }\n }\n}\n" + }, + "contracts/mock/LimitedMintingToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\ncontract LimitedMintingToken is ERC20, Ownable {\n struct MintData {\n uint256 dailyAllowance;\n mapping (address => uint256) lastMintTimestamp;\n mapping (address => uint256) todaysMintedAmount;\n }\n\n MintData public mintData;\n\n constructor(string memory _name, string memory _symbol, uint256 _dailyAllowance) ERC20(_name, _symbol) {\n mintData.dailyAllowance = _dailyAllowance;\n }\n\n function mint(address _holder, uint256 _amount) external {\n MintData storage data = mintData;\n\n (uint256 limit, bool fullLimit) = _currentLimit(data);\n\n require(limit > 0, \"This address already claimed the maximum daily amount\");\n\n uint256 lastTimestamp = data.lastMintTimestamp[msg.sender];\n uint256 mintedAmount = data.todaysMintedAmount[msg.sender];\n\n uint256 amount = _amount > limit ? limit : _amount;\n data.lastMintTimestamp[msg.sender] = fullLimit ? block.timestamp : lastTimestamp;\n data.todaysMintedAmount[msg.sender] = fullLimit ? amount : mintedAmount + amount;\n\n _mint(_holder, amount);\n }\n\n function mintApproveAndStake(IStakingBank _stakingBank, address _holder, uint256 _amount) external {\n _mint(_holder, _amount);\n _approve(_holder, address(_stakingBank), _amount);\n _stakingBank.receiveApproval(_holder);\n }\n\n function getDailyAllowance() external view returns (uint256) {\n return mintData.dailyAllowance;\n }\n\n function getName() external pure returns (bytes32) {\n return \"UMB\";\n }\n\n function setDailyAllowance(uint256 newDailyAllowance) public onlyOwner {\n MintData storage data = mintData;\n data.dailyAllowance = newDailyAllowance;\n }\n\n function _currentLimit(MintData storage data) internal view returns (uint256 limit, bool fullLimit) {\n uint256 lastMint = data.lastMintTimestamp[msg.sender];\n fullLimit = block.timestamp - lastMint >= 24 hours;\n\n uint256 usedLimit = data.todaysMintedAmount[msg.sender];\n\n limit = fullLimit ? data.dailyAllowance : data.dailyAllowance - usedLimit;\n }\n}\n" + }, + "contracts/mock/Token.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\n// please remember this is our dummy token!\n// it will be replaced by proper DPoS solution in future\ncontract Token is ERC20 {\n constructor(\n string memory _name,\n string memory _symbol) ERC20(_name, _symbol) {\n }\n\n function mint(address _holder, uint256 _amount) external {\n _mint(_holder, _amount);\n }\n\n function mintApproveAndStake(IStakingBank _stakingBank, address _holder, uint256 _amount) external {\n _mint(_holder, _amount);\n _approve(_holder, address(_stakingBank), _amount);\n _stakingBank.receiveApproval(_holder);\n }\n\n function getName() external pure returns (bytes32) {\n return \"UMB\";\n }\n}\n" + }, + "contracts/onChainFeeds/UmbrellaFeeds.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/IUmbrellaFeeds.sol\";\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IStakingBankStatic.sol\";\n\n/// @dev Main contract for all on-chain data.\n/// Check `UmbrellaFeedsReader` to see how to integrate.\n///\n/// @notice This contract can be destroyed and replaced with new one (with new address).\n/// For best gas efficiency you should pick one of two ways of integration:\n/// 1. make `UmbrellaFeeds` immutable and use fallback in case of selfdestruct. After new deployment, it is recommended\n/// to update address to avoid fallback and reduce gas cost to minimum. In long run this is most efficient solution,\n/// better than any proxy.\n/// 2. always check newest `UmbrellaFeeds` via `Regostry` and fallback will not be needed.\ncontract UmbrellaFeeds is IUmbrellaFeeds {\n bytes constant public ETH_PREFIX = \"\\x19Ethereum Signed Message:\\n32\";\n string constant public NAME = \"UmbrellaFeeds\";\n\n /// @dev deployment time, used for protect for unintentional destroy\n uint256 public immutable DEPLOYED_AT; // solhint-disable-line var-name-mixedcase\n\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\n /// resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev StakingBank contract where list of validators is stored\n IStakingBankStatic public immutable STAKING_BANK; // solhint-disable-line var-name-mixedcase\n\n /// @dev minimal number of signatures required for accepting price submission (PoA)\n uint16 public immutable REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\n\n /// @dev decimals for prices stored in this contract\n uint8 public immutable DECIMALS; // solhint-disable-line var-name-mixedcase\n\n /// @notice map of all prices stored in this contract, key for map is hash of feed name\n /// eg for \"ETH-USD\" feed, key will be hash(\"ETH-USD\")\n mapping (bytes32 => PriceData) private _prices;\n\n error ArraysDataDoNotMatch();\n error FeedNotExist();\n error NotEnoughSignatures();\n error InvalidSigner();\n error InvalidRequiredSignatures();\n error SignaturesOutOfOrder();\n error ECDSAInvalidSignatureS();\n error ECDSAInvalidSignatureV();\n error OldData();\n error ContractInUse();\n error ContractNotInitialised();\n\n /// @param _contractRegistry Registry address\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n /// @param _decimals decimals for prices stored in this contract\n constructor(\n IRegistry _contractRegistry,\n uint16 _requiredSignatures,\n uint8 _decimals\n ) {\n if (_requiredSignatures == 0) revert InvalidRequiredSignatures();\n\n REGISTRY = _contractRegistry;\n REQUIRED_SIGNATURES = _requiredSignatures;\n STAKING_BANK = IStakingBankStatic(_contractRegistry.requireAndGetAddress(\"StakingBank\"));\n DECIMALS = _decimals;\n DEPLOYED_AT = block.timestamp;\n }\n\n /// @dev destroys old contract\n /// there is sanity check that prevents abuse of destroy method\n /// @param _name string feed key to verify, that contract was initialised\n function destroy(string calldata _name) external {\n if (REGISTRY.getAddressByString(NAME) == address(this)) revert ContractInUse();\n\n if (_prices[keccak256(abi.encodePacked(_name))].timestamp == 0 && DEPLOYED_AT + 3 days > block.timestamp) {\n revert ContractNotInitialised();\n }\n\n selfdestruct(payable(msg.sender));\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function update(\n bytes32[] calldata _priceKeys,\n PriceData[] calldata _priceDatas,\n Signature[] calldata _signatures\n ) external {\n if (_priceKeys.length != _priceDatas.length) revert ArraysDataDoNotMatch();\n\n bytes32 priceDataHash = keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n verifySignatures(priceDataHash, _signatures);\n\n uint256 i;\n\n while (i < _priceDatas.length) {\n bytes32 priceKey = _priceKeys[i];\n\n // we do not allow for older prices\n // at the same time it prevents from reusing signatures\n if (_prices[priceKey].timestamp >= _priceDatas[i].timestamp) revert OldData();\n\n _prices[priceKey] = _priceDatas[i];\n\n // atm there is no need for events, so in order to save gas, we do not emit any\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n if (data[i].timestamp == 0) revert FeedNotExist();\n\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function prices(bytes32 _key) external view returns (PriceData memory data) {\n data = _prices[_key];\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceData(bytes32 _key) external view returns (PriceData memory data) {\n data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPrice(bytes32 _key) external view returns (uint128 price) {\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return data.price;\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp) {\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp);\n }\n\n function getPriceTimestampHeartbeat(bytes32 _key)\n external\n view\n returns (uint128 price, uint32 timestamp, uint24 heartbeat)\n {\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp, data.heartbeat);\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data) {\n bytes32 key = keccak256(abi.encodePacked(_name));\n data = _prices[key];\n }\n\n /// @dev helper method for QA purposes\n /// @return hash of data that are signed by validators (keys and priced data)\n function hashData(bytes32[] calldata _priceKeys, PriceData[] calldata _priceDatas)\n external\n view\n returns (bytes32)\n {\n return keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n }\n\n /// @param _hash hash of signed data\n /// @param _signatures array of validators signatures\n function verifySignatures(bytes32 _hash, Signature[] calldata _signatures) public view {\n address prevSigner = address(0x0);\n\n if (_signatures.length < REQUIRED_SIGNATURES) revert NotEnoughSignatures();\n\n address[] memory validators = new address[](REQUIRED_SIGNATURES);\n\n // to save gas we check only required number of signatures\n // case, where you can have part of signatures invalid but still enough valid in total is not supported\n for (uint256 i; i < REQUIRED_SIGNATURES;) {\n (uint8 v, bytes32 r, bytes32 s) = (_signatures[i].v, _signatures[i].r, _signatures[i].s);\n\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n revert ECDSAInvalidSignatureS();\n }\n\n if (uint8(v) != 27 && uint8(v) != 28) revert ECDSAInvalidSignatureV();\n\n address signer = recoverSigner(_hash, v, r, s);\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\n\n // because we check only required number of signatures, any invalid one will cause revert\n prevSigner = signer;\n validators[i] = signer;\n\n unchecked { i++; }\n }\n\n // bulk verification can optimise gas when we have 5 or more validators\n if (!STAKING_BANK.verifyValidators(validators)) revert InvalidSigner();\n }\n\n function getChainId() public view returns (uint256 id) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n id := chainid()\n }\n }\n\n /// @param _hash hashed of data\n /// @param _v part of signature\n /// @param _r part of signature\n /// @param _s part of signature\n /// @return signer address\n function recoverSigner(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _hash));\n return ecrecover(hash, _v, _r, _s);\n }\n\n /// @dev to follow Registrable interface\n function getName() public pure returns (bytes32) {\n return \"UmbrellaFeeds\";\n }\n}\n" + }, + "contracts/onChainFeeds/UmbrellaFeedsReader.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IUmbrellaFeeds.sol\";\n\n/// @dev This is optional price reader for just one feed.\n/// It comes with chanilink interface that makes migration process easier.\n/// For maximum gas optimisation it is recommended to use UmbrellaFeeds directly - simply follow this contract as\n/// a guide for integration.\n///\n/// This contract has build in fallback feature in case, `UmbrellaFeeds` will be replaced by newer contract.\n/// Fallback is transparent for the user, no additional setup is needed.\n///\n/// How fallback feature works? If data for provided key is empty (when UmbrellaFeeds was destroyed and replaced),\n/// contract will execute following procedure:\n/// 1. if data is empty, contract will check if there is new registered contract with requested data\n/// 2. if data is found in new contract it will be returned\n/// 3. if there is no data or there is no new contract tx will revert.\ncontract UmbrellaFeedsReader {\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\n /// resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev contract where all the feeds are stored\n address public immutable UMBRELLA_FEEDS; // solhint-disable-line var-name-mixedcase\n\n /// @dev key (hash of string key), under which feed is being stored\n bytes32 public immutable KEY; // solhint-disable-line var-name-mixedcase\n\n /// @dev string representation of feed key (feed name)\n string public description;\n\n /// @dev decimals for feed\n uint8 internal immutable _DECIMALS; // solhint-disable-line var-name-mixedcase\n\n error EmptyAddress();\n error FeedNotExist();\n\n /// @param _registry IRegistry address\n /// @param _umbrellaFeeds UmbrellaFeeds address\n /// @param _key price data key (before hashing)\n constructor(IRegistry _registry, IUmbrellaFeeds _umbrellaFeeds, string memory _key) {\n if (address(_registry) == address(0)) revert EmptyAddress();\n\n REGISTRY = _registry;\n UMBRELLA_FEEDS = address(_umbrellaFeeds);\n description = _key;\n _DECIMALS = _umbrellaFeeds.DECIMALS();\n\n bytes32 hash = keccak256(abi.encodePacked(_key));\n KEY = hash;\n\n // sanity check\n _umbrellaFeeds.getPriceData(hash);\n }\n\n /// @dev decimals for feed\n function decimals() external view returns (uint8) {\n return _DECIMALS;\n }\n\n /// @dev this method follows chainlink interface for easy migration, NOTE: not all returned data are covered!\n /// latestRoundData() raise exception when there is no data, instead of returning unset values,\n /// which could be misinterpreted as actual reported values.\n /// It DOES NOT raise when data is outdated (based on heartbeat and timestamp).\n /// @notice You can save some gas by doing call directly to `UMBRELLA_FEEDS` contract.\n /// @return uint80 originally `roundId`, not in use, always 0\n /// @return answer price\n /// @return uint256 originally `startedAt`, not in use, always 0\n /// @return updatedAt last timestamp data was updated\n /// @return uint80 originally `answeredInRound` not in use, always 0\n function latestRoundData()\n external\n view\n returns (\n uint80 /* roundId */,\n int256 answer,\n uint256 /* startedAt */,\n uint256 updatedAt,\n uint80 /* answeredInRound */\n )\n {\n IUmbrellaFeeds.PriceData memory priceData = _getPriceDataRaw();\n\n if (priceData.timestamp == 0) {\n priceData = _fallbackCall();\n }\n\n return (0, int256(uint256(priceData.price)), 0, priceData.timestamp, 0);\n }\n\n /// @dev this is main endpoint for reading feed. Feed is read from UmbrellaFeeds contract using hardcoded `KEY`.\n /// In case timestamp is empty (that means there is no data), contract will execute fallback call.\n /// @notice revert on empty data\n function getPriceData() external view returns (IUmbrellaFeeds.PriceData memory priceData) {\n priceData = _getPriceDataRaw();\n\n if (priceData.timestamp == 0) {\n priceData = _fallbackCall();\n }\n }\n\n /// @dev same as `getPriceData` but does not revert when no data\n function getPriceDataRaw() external view returns (IUmbrellaFeeds.PriceData memory priceData) {\n priceData = _getPriceDataRaw();\n\n if (priceData.timestamp == 0) {\n return _fallbackCallRaw();\n }\n }\n\n /// @dev same as `getPriceData` but does not revert when no data\n function _getPriceDataRaw() internal view returns (IUmbrellaFeeds.PriceData memory priceData) {\n (bool success, bytes memory data) = UMBRELLA_FEEDS.staticcall(\n abi.encodeWithSelector(IUmbrellaFeeds.prices.selector, KEY)\n );\n\n if (success && data.length != 0) {\n priceData = abi.decode(data, (IUmbrellaFeeds.PriceData));\n }\n }\n\n /// @dev it will revert on empty data\n function _fallbackCall() internal view returns (IUmbrellaFeeds.PriceData memory data) {\n address umbrellaFeeds = REGISTRY.getAddressByString(\"UmbrellaFeeds\");\n\n // if contract was NOT updated, fallback is not needed, data does not exist - revert\n if (umbrellaFeeds == UMBRELLA_FEEDS) revert FeedNotExist();\n\n data = IUmbrellaFeeds(umbrellaFeeds).getPriceData(KEY);\n }\n\n /// @dev it will not revert on empty data\n function _fallbackCallRaw() internal view returns (IUmbrellaFeeds.PriceData memory data) {\n address umbrellaFeeds = REGISTRY.getAddressByString(\"UmbrellaFeeds\");\n\n // if contract was updated, we do fallback\n if (umbrellaFeeds != UMBRELLA_FEEDS) {\n data = IUmbrellaFeeds(umbrellaFeeds).prices(KEY);\n }\n }\n}\n" + }, + "contracts/onChainFeeds/UmbrellaFeedsReaderFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\nimport \"./UmbrellaFeedsReader.sol\";\n\n/// @notice Factory to deploy UmbrellaFeedsReader contract\ncontract UmbrellaFeedsReaderFactory {\n /// @dev Registry contract where list of all addresses is stored. Used to resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev list of all readers\n mapping (bytes32 => UmbrellaFeedsReader) public readers;\n\n event NewUmbrellaFeedsReader(UmbrellaFeedsReader indexed umbrellaFeedsReader, string feedName);\n\n error EmptyAddress();\n\n constructor(IRegistry _registry) {\n if (address(_registry) == address(0)) revert EmptyAddress();\n\n REGISTRY = _registry;\n }\n\n /// @dev Method to deploy new UmbrellaFeedsReader for particular key.\n /// This deployment is optional and it can be done by anyone who needs it.\n /// Reader can be used to simplify migration from Chainlink to Umbrella.\n ///\n /// Check UmbrellaFeedsReader docs for more details.\n ///\n /// We not using minimal proxy because it does not allow for immutable variables.\n /// @param _feedName string Feed name that is registered in UmbrellaFeeds\n /// @return reader UmbrellaFeedsReader contract address, in case anyone wants to use it from Layer1\n function deploy(string memory _feedName) external returns (UmbrellaFeedsReader reader) {\n reader = deployed(_feedName);\n IUmbrellaFeeds umbrellaFeeds = IUmbrellaFeeds(REGISTRY.getAddressByString(\"UmbrellaFeeds\"));\n\n // if UmbrellaFeeds contract is up to date, there is no need to redeploy\n if (address(reader) != address(0) && address(reader.UMBRELLA_FEEDS()) == address(umbrellaFeeds)) {\n return reader;\n }\n\n reader = new UmbrellaFeedsReader(REGISTRY, umbrellaFeeds, _feedName);\n readers[hash(_feedName)] = reader;\n\n emit NewUmbrellaFeedsReader(reader, _feedName);\n }\n\n function deployed(string memory _feedName) public view returns (UmbrellaFeedsReader) {\n return readers[hash(_feedName)];\n }\n\n function hash(string memory _feedName) public pure returns (bytes32) {\n return keccak256(abi.encodePacked(_feedName));\n }\n\n /// @dev to follow Registrable interface\n function getName() public pure returns (bytes32) {\n return \"UmbrellaFeedsReaderFactory\";\n }\n}\n" + }, + "contracts/onChainFeeds/zk-link/UmbrellaFeeds.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../../interfaces/IUmbrellaFeeds.sol\";\nimport \"../../interfaces/IRegistry.sol\";\nimport \"../../interfaces/IStakingBankStatic.sol\";\n\n/// @dev Main contract for all on-chain data.\n/// Check `UmbrellaFeedsReader` to see how to integrate.\n///\n/// @notice This contract can be destroyed and replaced with new one (with new address).\n/// For best gas efficiency you should pick one of two ways of integration:\n/// 1. make `UmbrellaFeeds` immutable and use fallback in case of selfdestruct. After new deployment, it is recommended\n/// to update address to avoid fallback and reduce gas cost to minimum. In long run this is most efficient solution,\n/// better than any proxy.\n/// 2. always check newest `UmbrellaFeeds` via `Regostry` and fallback will not be needed.\ncontract UmbrellaFeeds is IUmbrellaFeeds {\n bytes constant public ETH_PREFIX = \"\\x19Ethereum Signed Message:\\n32\";\n string constant public NAME = \"UmbrellaFeeds\";\n\n /// @dev deployment time, used for protect for unintentional destroy\n uint256 public immutable DEPLOYED_AT; // solhint-disable-line var-name-mixedcase\n\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\n /// resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev StakingBank contract where list of validators is stored\n IStakingBankStatic public immutable STAKING_BANK; // solhint-disable-line var-name-mixedcase\n\n /// @dev minimal number of signatures required for accepting price submission (PoA)\n uint16 public immutable REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\n\n /// @dev decimals for prices stored in this contract\n uint8 public immutable DECIMALS; // solhint-disable-line var-name-mixedcase\n\n /// @dev in case selfdestruct is not supported, this flag will make sure contract is not usable anymore\n bool public disabled;\n\n /// @notice map of all prices stored in this contract, key for map is hash of feed name\n /// eg for \"ETH-USD\" feed, key will be hash(\"ETH-USD\")\n mapping (bytes32 => PriceData) private _prices;\n\n error SelfDestruct();\n error ArraysDataDoNotMatch();\n error FeedNotExist();\n error NotEnoughSignatures();\n error InvalidSigner();\n error InvalidRequiredSignatures();\n error SignaturesOutOfOrder();\n error ECDSAInvalidSignatureS();\n error ECDSAInvalidSignatureV();\n error OldData();\n error ContractInUse();\n error ContractNotInitialised();\n\n /// @param _contractRegistry Registry address\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n /// @param _decimals decimals for prices stored in this contract\n constructor(\n IRegistry _contractRegistry,\n uint16 _requiredSignatures,\n uint8 _decimals\n ) {\n if (_requiredSignatures == 0) revert InvalidRequiredSignatures();\n\n REGISTRY = _contractRegistry;\n REQUIRED_SIGNATURES = _requiredSignatures;\n STAKING_BANK = IStakingBankStatic(_contractRegistry.requireAndGetAddress(\"StakingBank\"));\n DECIMALS = _decimals;\n DEPLOYED_AT = block.timestamp;\n }\n\n /// @dev destroys old contract\n /// there is sanity check that prevents abuse of destroy method\n /// @param _name string feed key to verify, that contract was initialised\n function destroy(string calldata _name) external {\n if (REGISTRY.getAddressByString(NAME) == address(this)) revert ContractInUse();\n\n if (_prices[keccak256(abi.encodePacked(_name))].timestamp == 0 && DEPLOYED_AT + 3 days > block.timestamp) {\n revert ContractNotInitialised();\n }\n\n disabled = true;\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function update(\n bytes32[] calldata _priceKeys,\n PriceData[] calldata _priceDatas,\n Signature[] calldata _signatures\n ) external {\n if (disabled) revert SelfDestruct();\n if (_priceKeys.length != _priceDatas.length) revert ArraysDataDoNotMatch();\n\n bytes32 priceDataHash = keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n verifySignatures(priceDataHash, _signatures);\n\n uint256 i;\n\n while (i < _priceDatas.length) {\n bytes32 priceKey = _priceKeys[i];\n\n // we do not allow for older prices\n // at the same time it prevents from reusing signatures\n if (_prices[priceKey].timestamp >= _priceDatas[i].timestamp) revert OldData();\n\n _prices[priceKey] = _priceDatas[i];\n\n // atm there is no need for events, so in order to save gas, we do not emit any\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n if (disabled) revert SelfDestruct();\n\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n if (data[i].timestamp == 0) revert FeedNotExist();\n\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n if (disabled) revert SelfDestruct();\n\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function prices(bytes32 _key) external view returns (PriceData memory data) {\n if (disabled) revert SelfDestruct();\n\n data = _prices[_key];\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceData(bytes32 _key) external view returns (PriceData memory data) {\n if (disabled) revert SelfDestruct();\n\n data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPrice(bytes32 _key) external view returns (uint128 price) {\n if (disabled) revert SelfDestruct();\n\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return data.price;\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp) {\n if (disabled) revert SelfDestruct();\n\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp);\n }\n\n function getPriceTimestampHeartbeat(bytes32 _key)\n external\n view\n returns (uint128 price, uint32 timestamp, uint24 heartbeat)\n {\n if (disabled) revert SelfDestruct();\n\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp, data.heartbeat);\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data) {\n if (disabled) revert SelfDestruct();\n\n bytes32 key = keccak256(abi.encodePacked(_name));\n data = _prices[key];\n }\n\n /// @dev helper method for QA purposes\n /// @return hash of data that are signed by validators (keys and priced data)\n function hashData(bytes32[] calldata _priceKeys, PriceData[] calldata _priceDatas)\n external\n view\n returns (bytes32)\n {\n return keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n }\n\n /// @param _hash hash of signed data\n /// @param _signatures array of validators signatures\n function verifySignatures(bytes32 _hash, Signature[] calldata _signatures) public view {\n address prevSigner = address(0x0);\n\n if (_signatures.length < REQUIRED_SIGNATURES) revert NotEnoughSignatures();\n\n address[] memory validators = new address[](REQUIRED_SIGNATURES);\n\n // to save gas we check only required number of signatures\n // case, where you can have part of signatures invalid but still enough valid in total is not supported\n for (uint256 i; i < REQUIRED_SIGNATURES;) {\n (uint8 v, bytes32 r, bytes32 s) = (_signatures[i].v, _signatures[i].r, _signatures[i].s);\n\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n revert ECDSAInvalidSignatureS();\n }\n\n if (uint8(v) != 27 && uint8(v) != 28) revert ECDSAInvalidSignatureV();\n\n address signer = recoverSigner(_hash, v, r, s);\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\n\n // because we check only required number of signatures, any invalid one will cause revert\n prevSigner = signer;\n validators[i] = signer;\n\n unchecked { i++; }\n }\n\n // bulk verification can optimise gas when we have 5 or more validators\n if (!STAKING_BANK.verifyValidators(validators)) revert InvalidSigner();\n }\n\n function getChainId() public view returns (uint256 id) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n id := chainid()\n }\n }\n\n /// @param _hash hashed of data\n /// @param _v part of signature\n /// @param _r part of signature\n /// @param _s part of signature\n /// @return signer address\n function recoverSigner(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _hash));\n return ecrecover(hash, _v, _r, _s);\n }\n\n /// @dev to follow Registrable interface\n function getName() public pure returns (bytes32) {\n return \"UmbrellaFeeds\";\n }\n}\n" + }, + "contracts/Registry.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\n// Inheritance\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport \"./extensions/Registrable.sol\";\nimport \"./interfaces/IRegistry.sol\";\n\n/// @dev contracts registry\n/// protocol uses this registry to fetch current contract addresses\ncontract Registry is IRegistry, Ownable {\n /// name => contract address\n mapping(bytes32 => address) public registry;\n\n\n error NameNotRegistered();\n error ArraysDataDoNotMatch();\n\n /// @inheritdoc IRegistry\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external onlyOwner {\n if (_names.length != _destinations.length) revert ArraysDataDoNotMatch();\n\n for (uint i = 0; i < _names.length;) {\n registry[_names[i]] = _destinations[i];\n emit LogRegistered(_destinations[i], _names[i]);\n\n unchecked {\n i++;\n }\n }\n }\n\n /// @inheritdoc IRegistry\n function importContracts(address[] calldata _destinations) external onlyOwner {\n for (uint i = 0; i < _destinations.length;) {\n bytes32 name = Registrable(_destinations[i]).getName();\n registry[name] = _destinations[i];\n emit LogRegistered(_destinations[i], name);\n\n unchecked {\n i++;\n }\n }\n }\n\n /// @inheritdoc IRegistry\n function atomicUpdate(address _newContract) external onlyOwner {\n Registrable(_newContract).register();\n\n bytes32 name = Registrable(_newContract).getName();\n address oldContract = registry[name];\n registry[name] = _newContract;\n\n Registrable(oldContract).unregister();\n\n emit LogRegistered(_newContract, name);\n }\n\n /// @inheritdoc IRegistry\n function requireAndGetAddress(bytes32 name) external view returns (address) {\n address _foundAddress = registry[name];\n if (_foundAddress == address(0)) revert NameNotRegistered();\n\n return _foundAddress;\n }\n\n /// @inheritdoc IRegistry\n function getAddress(bytes32 _bytes) external view returns (address) {\n return registry[_bytes];\n }\n\n /// @inheritdoc IRegistry\n function getAddressByString(string memory _name) public view returns (address) {\n return registry[stringToBytes32(_name)];\n }\n\n /// @inheritdoc IRegistry\n function stringToBytes32(string memory _string) public pure returns (bytes32 result) {\n bytes memory tempEmptyStringTest = bytes(_string);\n\n if (tempEmptyStringTest.length == 0) {\n return 0x0;\n }\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n result := mload(add(_string, 32))\n }\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStatic.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/StakingBankStaticNotSupported.sol\";\n\n/// @dev Because we are using PoA in UMB oracle, staked balance does not matter. What's matter is, if signer is\n/// validator or not. In this case we can optimise `StakingBank` and make it static for better gas performance.\nabstract contract StakingBankStatic is StakingBankStaticNotSupported {\n uint256 public constant ONE = 1e18;\n\n uint256 public immutable NUMBER_OF_VALIDATORS; // solhint-disable-line var-name-mixedcase\n uint256 public immutable TOTAL_SUPPLY; // solhint-disable-line var-name-mixedcase\n\n constructor(uint256 _validatorsCount) {\n NUMBER_OF_VALIDATORS = _validatorsCount;\n TOTAL_SUPPLY = _validatorsCount * ONE;\n\n _assertValidSetup(_validatorsCount);\n }\n\n function balances(address _validator) external view returns (uint256) {\n return _isValidator(_validator) ? ONE : 0;\n }\n\n function verifyValidators(address[] calldata _validators) external view returns (bool) {\n for (uint256 i; i < _validators.length;) {\n if (!_isValidator(_validators[i])) return false;\n unchecked { i++; }\n }\n\n return true;\n }\n\n function getNumberOfValidators() external view returns (uint256) {\n return NUMBER_OF_VALIDATORS;\n }\n\n function getAddresses() external view returns (address[] memory) {\n return _addresses();\n }\n\n function getBalances() external view returns (uint256[] memory allBalances) {\n allBalances = new uint256[](NUMBER_OF_VALIDATORS);\n\n for (uint256 i; i < NUMBER_OF_VALIDATORS;) {\n allBalances[i] = ONE;\n\n unchecked {\n // we will not have enough data to overflow\n i++;\n }\n }\n }\n\n function addresses(uint256 _ix) external view returns (address) {\n return _addresses()[_ix];\n }\n\n function validators(address _id) external view virtual returns (address id, string memory location);\n\n /// @dev to follow ERC20 interface\n function balanceOf(address _account) external view returns (uint256) {\n return _isValidator(_account) ? ONE : 0;\n }\n\n /// @dev to follow ERC20 interface\n function totalSupply() external view returns (uint256) {\n return TOTAL_SUPPLY;\n }\n\n /// @dev to follow Registrable interface\n function getName() external pure returns (bytes32) {\n return \"StakingBank\";\n }\n\n /// @dev to follow Registrable interface\n function register() external pure {\n // there are no requirements atm\n }\n\n /// @dev to follow Registrable interface\n function unregister() external pure {\n // there are no requirements atm\n }\n\n function _addresses() internal view virtual returns (address[] memory);\n\n function _isValidator(address _validator) internal view virtual returns (bool);\n\n function _assertValidSetup(uint256 _validatorsCount) internal view virtual{\n address[] memory list = _addresses();\n require(list.length == _validatorsCount);\n\n for (uint256 i; i < _validatorsCount;) {\n require(_isValidator(list[i]));\n\n unchecked { i ++; }\n }\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticCI.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticCI is StakingBankStatic {\n // 0x87630b2d1de0fbd5044eb6891b3d9d98c34c8d310c852f98550ba774480e47cc\n address public constant VALIDATOR_0 = 0x2fFd013AaA7B5a7DA93336C2251075202b33FB2B;\n // 0x3f1e8b94c70206bf816c1ed0b15ad98bdf225ae4c6e7e4eee6cdbcf706fda2ae\n address public constant VALIDATOR_1 = 0x43158ea338Ff13D0bDa0c3EB969B9EA5a624E7Cc;\n // 0x5da6b84117504d06b5dcd52b990d76965d2882f4e5852eb610bc76e4209b10d7\n address public constant VALIDATOR_2 = 0x9Fd8DD0627b9A32399Fd115c4725C7e17BC40e6d;\n // 0x1e5012671de3332ad0b43661984e94ab0e405bffddc9d3e863055040bab354b8\n address public constant VALIDATOR_3 = 0xa3F3659E469b7aE0b249546338DEdc0b684edB05;\n // 0x0edc1e35ea7701ddac703286674e79f04addbf5d2f6162fabc19d39bd3dc6662\n address public constant VALIDATOR_4 = 0xB98A954B9036DF144d685E910bfbAEC6B33A8d11;\n // 0x23c601ae397441f3ef6f1075dcb0031ff17fb079837beadaf3c84d96c6f3e569\n address public constant VALIDATOR_5 = 0xE5904695748fe4A84b40b3fc79De2277660BD1D3;\n\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.ci.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.ci.umb.network\");\n if (_id == VALIDATOR_2) return (_id, \"https://validator3.ci.umb.network\");\n if (_id == VALIDATOR_3) return (_id, \"https://validator4.ci.umb.network\");\n if (_id == VALIDATOR_4) return (_id, \"https://validator5.ci.umb.network\");\n if (_id == VALIDATOR_5) return (_id, \"https://validator6.ci.umb.network\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n list[2] = VALIDATOR_2;\n list[3] = VALIDATOR_3;\n list[4] = VALIDATOR_4;\n list[5] = VALIDATOR_5;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0\n || _validator == VALIDATOR_1\n || _validator == VALIDATOR_2\n || _validator == VALIDATOR_3\n || _validator == VALIDATOR_4\n || _validator == VALIDATOR_5\n );\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticDev.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticDev is StakingBankStatic {\n address public constant VALIDATOR_0 = 0xDc3eBc37DA53A644D67E5E3b5BA4EEF88D969d5C;\n address public constant VALIDATOR_1 = 0x998cb7821e605cC16b6174e7C50E19ADb2Dd2fB0;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.dev.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.dev.umb.network\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0 || _validator == VALIDATOR_1);\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticLocal.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticLocal is StakingBankStatic {\n address public constant VALIDATOR_0 = 0xeAD9C93b79Ae7C1591b1FB5323BD777E86e150d4;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"localhost\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0);\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticProd.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\ncontract StakingBankStaticProd is StakingBankStatic {\n address public constant VALIDATOR_0 = 0x977Ba523420110e230643B772Fe9cF955e11dA7B;\n address public constant VALIDATOR_1 = 0xe2422b23e52bc13ebA04d7FbB9F332Deb43360fB;\n\n // external order is based on validators submits on AVAX for Apr 2023\n address public constant VALIDATOR_2 = 0x57F404aD75e371c1A539589C1eFCA12e0C6980AD;\n address public constant VALIDATOR_3 = 0xD56C6A4f64E0bD70260472d1DB6Cf5825858CB0d;\n address public constant VALIDATOR_4 = 0x93FdcAB283b0BcAc48157590af482E1CFd6af6aC;\n address public constant VALIDATOR_5 = 0xCd733E06B06083d52fC5867E8E3432aA5c103A38;\n address public constant VALIDATOR_6 = 0x42e210b110c6aa49CdfA7ceF1444Aa4719653111;\n address public constant VALIDATOR_7 = 0x501731c6a69803a53Ec6c3e12f293c247cE1092B;\n address public constant VALIDATOR_8 = 0x8bF9661F1b247522C75DD0FE84355aD2EfF27144;\n address public constant VALIDATOR_9 = 0x281754Ab58391A478B7aA4E7f39991CfB41118c4;\n address public constant VALIDATOR_10 = 0x57A51D5BDcE188c2295fCA3b4687475a54E65A02;\n address public constant VALIDATOR_11 = 0x2F85824B2B38F179E451988670935d315b5b9692;\n address public constant VALIDATOR_12 = 0xA7241994267682de4dE7Ef62f52dc2C783d1784B;\n address public constant VALIDATOR_13 = 0x6eEd457C20603EDAE50C3A112CAA1a9425321bD0;\n address public constant VALIDATOR_14 = 0xC5a7650c2725a7B6A39f15cb9FbffC7af357AFeb;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n // solhint-disable-next-line code-complexity\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.umb.network\");\n if (_id == VALIDATOR_2) return (_id, \"https://umbrella.artemahr.tech\");\n if (_id == VALIDATOR_3) return (_id, \"https://umb.vtabsolutions.com:3030\");\n if (_id == VALIDATOR_4) return (_id, \"https://umbrella.crazywhale.es\");\n if (_id == VALIDATOR_5) return (_id, \"https://umbrella-node.gateomega.com\");\n if (_id == VALIDATOR_6) return (_id, \"https://umb.anorak.technology\");\n if (_id == VALIDATOR_7) return (_id, \"https://umbrella.validator.infstones.io\");\n if (_id == VALIDATOR_8) return (_id, \"https://umb.hashkey.cloud\");\n if (_id == VALIDATOR_9) return (_id, \"http://umbrella.staking4all.org:3000\");\n if (_id == VALIDATOR_10) return (_id, \"http://5.161.78.230:3000\");\n if (_id == VALIDATOR_11) return (_id, \"https://umb-api.staking.rocks\");\n if (_id == VALIDATOR_12) return (_id, \"https://rpc.urbanhq.net\");\n if (_id == VALIDATOR_13) return (_id, \"https://umbrella-node.ankastake.com\");\n if (_id == VALIDATOR_14) return (_id, \"https://umbrella.tchambrella.com\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n list[2] = VALIDATOR_2;\n list[3] = VALIDATOR_3;\n list[4] = VALIDATOR_4;\n list[5] = VALIDATOR_5;\n list[6] = VALIDATOR_6;\n list[7] = VALIDATOR_7;\n list[8] = VALIDATOR_8;\n list[9] = VALIDATOR_9;\n list[10] = VALIDATOR_10;\n list[11] = VALIDATOR_11;\n list[12] = VALIDATOR_12;\n list[13] = VALIDATOR_13;\n list[14] = VALIDATOR_14;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (\n _validator == VALIDATOR_0\n || _validator == VALIDATOR_1\n || _validator == VALIDATOR_2\n || _validator == VALIDATOR_3\n || _validator == VALIDATOR_4\n || _validator == VALIDATOR_5\n || _validator == VALIDATOR_6\n || _validator == VALIDATOR_7\n || _validator == VALIDATOR_8\n || _validator == VALIDATOR_9\n || _validator == VALIDATOR_10\n || _validator == VALIDATOR_11\n || _validator == VALIDATOR_12\n || _validator == VALIDATOR_13\n || _validator == VALIDATOR_14\n );\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticSbx.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticSbx is StakingBankStatic {\n address public constant VALIDATOR_0 = 0xE3bDa0C6E1fBB111091Dfef6f22a673b20Ea5F50;\n address public constant VALIDATOR_1 = 0xc1773490F00963CBAb3841fc07C1a0796E658Ba2;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.sbx.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.sbx.umb.network\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0 || _validator == VALIDATOR_1);\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": false, + "runs": 0 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/bnb_production/Chain.json b/deployments/bnb_production/Chain.json index 0efc2f86..52a56afe 100644 --- a/deployments/bnb_production/Chain.json +++ b/deployments/bnb_production/Chain.json @@ -1,5 +1,5 @@ { - "address": "0x5EF742E88726158081AF5F6111C19c4659537033", + "address": "0x4bcEb3098A035aE81bf1Fd5Ee445a205d84F7cbF", "abi": [ { "inputs": [ @@ -1046,47 +1046,47 @@ "type": "function" } ], - "transactionHash": "0xabab868e8d106ca53fe6620da37dfd2e030e2ee1d7bec856999749953b06f045", + "transactionHash": "0x8e4f61440cc6534c2a21a0992d829c60f9a510738880127efb5b6fece2aa5d54", "receipt": { "to": null, "from": "0xA6e4fFa19B213AbeA258ae72e8e1a209B9E543e7", - "contractAddress": "0x5EF742E88726158081AF5F6111C19c4659537033", - "transactionIndex": 21, - "gasUsed": "4800015", - "logsBloom": "0x00000000000000000000000000000008000000000000000000800000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000020400000000000000000000000000000000000000000000000000002000000001000000000000000000000000000000000000002000000000000010000000000000400000000000000000000000000000000000020000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x34e28fefc899a1a75fe1f674da75e05b34499b6246b9542eb3c125edaf14f878", - "transactionHash": "0xabab868e8d106ca53fe6620da37dfd2e030e2ee1d7bec856999749953b06f045", + "contractAddress": "0x4bcEb3098A035aE81bf1Fd5Ee445a205d84F7cbF", + "transactionIndex": 25, + "gasUsed": "4801537", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000400000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000020400000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000010000000000000400000000000000000000000000000000000020000000000000000000000020000000100000000000000000000000000000000000000000000008000000000000", + "blockHash": "0x2df15c6f16882de4ff9cb259f136c253c9cc02faf365797dee12aa185345a70c", + "transactionHash": "0x8e4f61440cc6534c2a21a0992d829c60f9a510738880127efb5b6fece2aa5d54", "logs": [ { - "transactionIndex": 21, - "blockNumber": 33282912, - "transactionHash": "0xabab868e8d106ca53fe6620da37dfd2e030e2ee1d7bec856999749953b06f045", - "address": "0x5EF742E88726158081AF5F6111C19c4659537033", + "transactionIndex": 25, + "blockNumber": 43568890, + "transactionHash": "0x8e4f61440cc6534c2a21a0992d829c60f9a510738880127efb5b6fece2aa5d54", + "address": "0x4bcEb3098A035aE81bf1Fd5Ee445a205d84F7cbF", "topics": [ "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x000000000000000000000000a6e4ffa19b213abea258ae72e8e1a209b9e543e7" ], "data": "0x", - "logIndex": 42, - "blockHash": "0x34e28fefc899a1a75fe1f674da75e05b34499b6246b9542eb3c125edaf14f878" + "logIndex": 60, + "blockHash": "0x2df15c6f16882de4ff9cb259f136c253c9cc02faf365797dee12aa185345a70c" }, { - "transactionIndex": 21, - "blockNumber": 33282912, - "transactionHash": "0xabab868e8d106ca53fe6620da37dfd2e030e2ee1d7bec856999749953b06f045", - "address": "0x5EF742E88726158081AF5F6111C19c4659537033", + "transactionIndex": 25, + "blockNumber": 43568890, + "transactionHash": "0x8e4f61440cc6534c2a21a0992d829c60f9a510738880127efb5b6fece2aa5d54", + "address": "0x4bcEb3098A035aE81bf1Fd5Ee445a205d84F7cbF", "topics": [ "0x02ff77a0f68d11f7efb906f331b2dda82916de8ba9c37dda2a95817936a530ec", "0x000000000000000000000000a6e4ffa19b213abea258ae72e8e1a209b9e543e7" ], "data": "0x00000000000000000000000000000000000000000000000000000000000000f0", - "logIndex": 43, - "blockHash": "0x34e28fefc899a1a75fe1f674da75e05b34499b6246b9542eb3c125edaf14f878" + "logIndex": 61, + "blockHash": "0x2df15c6f16882de4ff9cb259f136c253c9cc02faf365797dee12aa185345a70c" } ], - "blockNumber": 33282912, - "cumulativeGasUsed": "6557185", + "blockNumber": 43568890, + "cumulativeGasUsed": "6951371", "status": 1, "byzantium": true }, @@ -1097,7 +1097,7 @@ false ], "numDeployments": 1, - "solcInputHash": "4db3e1d3dd51dbe508dc0a6a04352df6", + "solcInputHash": "dc68422c0ad35a4fe46d461b096b9383", "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"_contractRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"_padding\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"_requiredSignatures\",\"type\":\"uint16\"},{\"internalType\":\"bool\",\"name\":\"_allowForMixedType\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyDeprecated\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArraysDataDoNotMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BlockSubmittedToFastOrDataToOld\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractNotReady\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FCDOverflow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContractType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoChangeToState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotEnoughSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyOwnerOrRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfOrder\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnregisterFirst\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"deprecator\",\"type\":\"address\"}],\"name\":\"LogDeprecation\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"blockId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"staked\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"power\",\"type\":\"uint256\"}],\"name\":\"LogMint\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"executor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"timePadding\",\"type\":\"uint32\"}],\"name\":\"LogPadding\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"blockId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"vote\",\"type\":\"uint256\"}],\"name\":\"LogVoter\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ETH_PREFIX\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_blockId\",\"type\":\"uint256\"}],\"name\":\"blocks\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"dataTimestamp\",\"type\":\"uint32\"}],\"internalType\":\"struct BaseChain.Block\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blocksCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blocksCountOffset\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_offset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_items\",\"type\":\"uint256\"}],\"name\":\"bytesToBytes32Array\",\"outputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"contractRegistry\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deprecate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"fcds\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"dataTimestamp\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockId\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"getBlockIdAtTimestamp\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_blockId\",\"type\":\"uint32\"}],\"name\":\"getBlockRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_blockId\",\"type\":\"uint32\"}],\"name\":\"getBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConsensusData\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"blocksCountOffset\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"sequence\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"lastTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"padding\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"deprecated\",\"type\":\"bool\"}],\"internalType\":\"struct BaseChain.ConsensusData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getCurrentIntValue\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"value\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getCurrentValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_keys\",\"type\":\"bytes32[]\"}],\"name\":\"getCurrentValues\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"uint32[]\",\"name\":\"timestamps\",\"type\":\"uint32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestBlockId\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLeaderAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"getLeaderAddressAtTime\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_numberOfValidators\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"getLeaderIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNextLeaderAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStatus\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"timePadding\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"lastDataTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"lastId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"nextLeader\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"nextBlockId\",\"type\":\"uint32\"},{\"internalType\":\"address[]\",\"name\":\"validators\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"powers\",\"type\":\"uint256[]\"},{\"internalType\":\"string[]\",\"name\":\"locations\",\"type\":\"string[]\"},{\"internalType\":\"uint256\",\"name\":\"staked\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"minSignatures\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_key\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_value\",\"type\":\"bytes\"}],\"name\":\"hashLeaf\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isForeign\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastBlockId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_affidavit\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"_v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"_r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_s\",\"type\":\"bytes32\"}],\"name\":\"recoverSigner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"register\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"requiredSignatures\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"roots\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"_padding\",\"type\":\"uint16\"}],\"name\":\"setPadding\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stakingBank\",\"outputs\":[{\"internalType\":\"contract IStakingBank\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stakingBankContract\",\"outputs\":[{\"internalType\":\"contract IStakingBank\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_dataTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"_root\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"_keys\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_values\",\"type\":\"uint256[]\"},{\"internalType\":\"uint8[]\",\"name\":\"_v\",\"type\":\"uint8[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"_r\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"_s\",\"type\":\"bytes32[]\"}],\"name\":\"submit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"tokenContract\",\"outputs\":[{\"internalType\":\"contract ERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_proof\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"_root\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_leaf\",\"type\":\"bytes32\"}],\"name\":\"verifyProof\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_blockId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"_proof\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"_key\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_value\",\"type\":\"bytes\"}],\"name\":\"verifyProofForBlock\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"_blockIds\",\"type\":\"uint32[]\"},{\"internalType\":\"bytes\",\"name\":\"_proofs\",\"type\":\"bytes\"},{\"internalType\":\"uint256[]\",\"name\":\"_proofItemsCounter\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"_leaves\",\"type\":\"bytes32[]\"}],\"name\":\"verifyProofs\",\"outputs\":[{\"internalType\":\"bool[]\",\"name\":\"results\",\"type\":\"bool[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"blocks(uint256)\":{\"params\":{\"_blockId\":\"ID of submitted block\"},\"returns\":{\"_0\":\"block data (root + timestamp)\"}},\"blocksCount()\":{\"details\":\"number of blocks (consensus rounds) saved in this contract\"},\"bytesToBytes32Array(bytes,uint256,uint256)\":{\"details\":\"this is helper method, that extracts one merkle proof from many hashed provided as bytes\",\"params\":{\"_data\":\"many hashes as bytes\",\"_items\":\"how many hashes to extract\",\"_offset\":\"this is starting point for extraction\"},\"returns\":{\"_0\":\"merkle proof (array of bytes32 hashes)\"}},\"constructor\":{\"params\":{\"_allowForMixedType\":\"we have two \\\"types\\\" of Chain: HomeChain and ForeignChain, when we redeploying we don't want to mix up them, so we checking, if new Chain has the same type as current one. However, when we will be switching from one homechain to another one, we have to allow for this mixing up. This flag will tell contract, if this is the case.\",\"_contractRegistry\":\"Registry address\",\"_padding\":\"required \\\"space\\\" between blocks in seconds\",\"_requiredSignatures\":\"number of required signatures for accepting consensus submission\"}},\"getBlockId()\":{\"returns\":{\"_0\":\"current block ID please note, that current ID is not the same as last ID, current means that once padding pass, ID will switch to next one and it will be pointing to empty submit until submit for that ID is done\"}},\"getBlockIdAtTimestamp(uint256)\":{\"details\":\"calculates block ID for provided timestamp this function does not works for past timestamps\",\"params\":{\"_timestamp\":\"current or future timestamp\"},\"returns\":{\"_0\":\"block ID for provided timestamp\"}},\"getBlockRoot(uint32)\":{\"params\":{\"_blockId\":\"consensus ID\"},\"returns\":{\"_0\":\"root for provided consensus ID\"}},\"getBlockTimestamp(uint32)\":{\"params\":{\"_blockId\":\"consensus ID\"},\"returns\":{\"_0\":\"timestamp for provided consensus ID\"}},\"getConsensusData()\":{\"details\":\"getter for `_consensusData`\"},\"getCurrentIntValue(bytes32)\":{\"details\":\"getter for single FCD value in case its type is `int`\",\"params\":{\"_key\":\"FCD key\"},\"returns\":{\"timestamp\":\"FCD timestamp\",\"value\":\"FCD value\"}},\"getCurrentValue(bytes32)\":{\"details\":\"getter for single FCD value\",\"params\":{\"_key\":\"FCD key\"},\"returns\":{\"timestamp\":\"FCD timestamp\",\"value\":\"FCD value\"}},\"getCurrentValues(bytes32[])\":{\"details\":\"batch getter for FCDs\",\"params\":{\"_keys\":\"FCDs keys to fetch\"},\"returns\":{\"timestamps\":\"array of FCDs timestamps\",\"values\":\"array of FCDs values\"}},\"getLatestBlockId()\":{\"returns\":{\"_0\":\"last submitted block ID, please note, that on deployment, when there is no submission for this contract block for last ID will be available in previous contract\"}},\"getLeaderAddress()\":{\"returns\":{\"_0\":\"address of current leader\"}},\"getLeaderAddressAtTime(uint256)\":{\"params\":{\"_timestamp\":\"timestamp for which you want to calculate leader address\"},\"returns\":{\"_0\":\"leader address for provider timestamp\"}},\"getLeaderIndex(uint256,uint256)\":{\"params\":{\"_numberOfValidators\":\"total number of validators\",\"_timestamp\":\"timestamp for which you want to calculate index\"},\"returns\":{\"_0\":\"leader index, use it for StakingBank.addresses[index] to fetch leader address\"}},\"getName()\":{\"returns\":{\"_0\":\"contract name as bytes32\"}},\"getNextLeaderAddress()\":{\"returns\":{\"_0\":\"address of leader for next second\"}},\"getStatus()\":{\"details\":\"helper method that returns all important data about current state of contract\",\"returns\":{\"blockNumber\":\"`block.number`\",\"lastDataTimestamp\":\"timestamp for last submitted consensus\",\"lastId\":\"ID of last submitted consensus\",\"locations\":\"array of all validators locations\",\"minSignatures\":\"`this.requiredSignatures`\",\"nextBlockId\":\"block ID for `block.timestamp + padding`\",\"nextLeader\":\"leader for `block.timestamp + 1`\",\"powers\":\"array of all validators powers\",\"staked\":\"total UMB staked by validators\",\"timePadding\":\"`this.padding`\",\"validators\":\"array of all validators addresses\"}},\"hashLeaf(bytes,bytes)\":{\"details\":\"creates leaf hash, that has is used in merkle tree\",\"params\":{\"_key\":\"key under which we store the value\",\"_value\":\"value itself as bytes\"},\"returns\":{\"_0\":\"leaf hash\"}},\"isForeign()\":{\"returns\":{\"_0\":\"TRUE if contract is ForeignChain, FALSE otherwise\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"recoverSigner(bytes32,uint8,bytes32,bytes32)\":{\"params\":{\"_affidavit\":\"root and FCDs hashed together\",\"_r\":\"part of signature\",\"_s\":\"part of signature\",\"_v\":\"part of signature\"},\"returns\":{\"_0\":\"signer address\"}},\"register()\":{\"details\":\"this method will be called as a first method in registration process when old contract will be replaced when called, old contract address is still in registry\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setPadding(uint16)\":{\"details\":\"setter for `padding`\"},\"stakingBankContract()\":{\"details\":\"helper method for fetching StakingBank address\"},\"submit(uint32,bytes32,bytes32[],uint256[],uint8[],bytes32[],bytes32[])\":{\"details\":\"method for submitting consensus data\",\"params\":{\"_dataTimestamp\":\"consensus timestamp, this is time for all data in merkle tree including FCDs\",\"_keys\":\"FCDs keys\",\"_r\":\"array of `r` part of validators signatures\",\"_root\":\"merkle root\",\"_s\":\"array of `s` part of validators signatures\",\"_v\":\"array of `v` part of validators signatures\",\"_values\":\"FCDs values\"}},\"tokenContract()\":{\"details\":\"helper method for fetching UMB address\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"unregister()\":{\"details\":\"this method will be called as a last method in registration process when old contract will be replaced when called, new contract address is already in registry\"},\"verifyProof(bytes32[],bytes32,bytes32)\":{\"details\":\"verifies if the leaf is valid leaf for merkle tree\",\"params\":{\"_leaf\":\"leaf hash\",\"_proof\":\"merkle proof for merkle tree\",\"_root\":\"merkle root\"},\"returns\":{\"_0\":\"TRUE if `_leaf` is valid, FALSE otherwise\"}},\"verifyProofForBlock(uint256,bytes32[],bytes,bytes)\":{\"details\":\"verifies, if provided key-value pair was part of consensus\",\"params\":{\"_blockId\":\"consensus ID for which we doing a check\",\"_key\":\"pair key\",\"_proof\":\"merkle proof for pair\",\"_value\":\"pair value\"},\"returns\":{\"_0\":\"TRUE if key-value par was part of consensus, FALSE otherwise\"}},\"verifyProofs(uint32[],bytes,uint256[],bytes32[])\":{\"details\":\"batch method for data verification\",\"params\":{\"_blockIds\":\"consensus IDs for which we doing a checks\",\"_leaves\":\"array of merkle leaves\",\"_proofItemsCounter\":\"array of counters, each counter tells how many hashes proof for each leaf has\",\"_proofs\":\"merkle proofs for all pair, sequence of hashes provided as bytes\"},\"returns\":{\"results\":\"array of verification results, TRUE if leaf is part of consensus, FALSE otherwise\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"deprecate()\":{\"notice\":\"it allows to deprecate contract manually Only new Registry calls `unregister()` where we set deprecated to true In old Registries we don't have this feature, so in order to safely redeploy new Chain we will have to first deprecate current contract manually, then register new contract\"},\"register()\":{\"notice\":\"if this method needs to be called manually (not from Registry) it is important to do it as part of tx batch eg using multisig, we should prepare set of transactions and confirm them all at once\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Chain.sol\":\"Chain\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":0},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0x24e0364e503a9bbde94c715d26573a76f14cd2a202d45f96f52134ab806b67b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\\n * instead returning `false` on failure. This behavior is nonetheless\\n * conventional and does not conflict with the expectations of ERC20\\n * applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * The default value of {decimals} is 18. To select a different value for\\n * {decimals} you should overload it.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n * overridden;\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\\n * `transferFrom`. This is semantically equivalent to an infinite approval.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * NOTE: Does not update the allowance if the current allowance\\n * is the maximum `uint256`.\\n *\\n * Requirements:\\n *\\n * - `from` and `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) public virtual override returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, amount);\\n _transfer(from, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, allowance(owner, spender) + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n uint256 currentAllowance = allowance(owner, spender);\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n */\\n function _transfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {\\n require(from != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(to != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, amount);\\n\\n uint256 fromBalance = _balances[from];\\n require(fromBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[from] = fromBalance - amount;\\n }\\n _balances[to] += amount;\\n\\n emit Transfer(from, to, amount);\\n\\n _afterTokenTransfer(from, to, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n _balances[account] += amount;\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n }\\n _totalSupply -= amount;\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(\\n address owner,\\n address spender,\\n uint256 amount\\n ) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\\n *\\n * Does not update the allowance amount in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Might emit an {Approval} event.\\n */\\n function _spendAllowance(\\n address owner,\\n address spender,\\n uint256 amount\\n ) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance != type(uint256).max) {\\n require(currentAllowance >= amount, \\\"ERC20: insufficient allowance\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - amount);\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {}\\n}\\n\",\"keccak256\":\"0xe0c8b625a79bac0fe80f17cfb521e072805cc9cef1c96a5caf45b264e74812fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/cryptography/MerkleProof.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev These functions deal with verification of Merkle Trees proofs.\\n *\\n * The proofs can be generated using the JavaScript library\\n * https://github.com/miguelmota/merkletreejs[merkletreejs].\\n * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.\\n *\\n * See `test/utils/cryptography/MerkleProof.test.js` for some examples.\\n *\\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\\n * hashing, or use a hash function other than keccak256 for hashing leaves.\\n * This is because the concatenation of a sorted pair of internal nodes in\\n * the merkle tree could be reinterpreted as a leaf value.\\n */\\nlibrary MerkleProof {\\n /**\\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\\n * defined by `root`. For this, a `proof` must be provided, containing\\n * sibling hashes on the branch from the leaf to the root of the tree. Each\\n * pair of leaves and each pair of pre-images are assumed to be sorted.\\n */\\n function verify(\\n bytes32[] memory proof,\\n bytes32 root,\\n bytes32 leaf\\n ) internal pure returns (bool) {\\n return processProof(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\\n * hash matches the root of the tree. When processing the proof, the pairs\\n * of leafs & pre-images are assumed to be sorted.\\n *\\n * _Available since v4.4._\\n */\\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n bytes32 proofElement = proof[i];\\n if (computedHash <= proofElement) {\\n // Hash(current computed hash + current element of the proof)\\n computedHash = _efficientHash(computedHash, proofElement);\\n } else {\\n // Hash(current element of the proof + current computed hash)\\n computedHash = _efficientHash(proofElement, computedHash);\\n }\\n }\\n return computedHash;\\n }\\n\\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\\n assembly {\\n mstore(0x00, a)\\n mstore(0x20, b)\\n value := keccak256(0x00, 0x40)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaaa504ac17eb0298dcdf5733ce24021b4914f035b97f4400b92827341d3facb3\",\"license\":\"MIT\"},\"@umb-network/toolbox/dist/contracts/lib/ValueDecoder.sol\":{\"content\":\"//SPDX-License-Identifier: Unlicensed\\npragma solidity >=0.6.8;\\n\\nlibrary ValueDecoder {\\n function toUint(bytes memory _bytes) internal pure returns (uint256 value) {\\n assembly {\\n value := mload(add(_bytes, 32))\\n }\\n }\\n\\n function toUint(bytes32 _bytes) internal pure returns (uint256 value) {\\n assembly {\\n value := _bytes\\n }\\n }\\n\\n function toInt(uint224 u) internal pure returns (int256) {\\n int224 i;\\n uint224 max = type(uint224).max;\\n\\n if (u <= (max - 1) / 2) { // positive values\\n assembly {\\n i := add(u, 0)\\n }\\n\\n return i;\\n } else { // negative values\\n assembly {\\n i := sub(sub(u, max), 1)\\n }\\n }\\n\\n return i;\\n }\\n}\\n\\n\",\"keccak256\":\"0x4c27669880111dd724930e6e2cb0baefdb3a8b7b2d6ffc0ec5c5534bc678a852\",\"license\":\"Unlicensed\"},\"contracts/BaseChain.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\\\";\\nimport \\\"@umb-network/toolbox/dist/contracts/lib/ValueDecoder.sol\\\";\\n\\nimport \\\"./interfaces/IBaseChainV1.sol\\\";\\nimport \\\"./interfaces/IStakingBank.sol\\\";\\nimport \\\"./extensions/Registrable.sol\\\";\\nimport \\\"./Registry.sol\\\";\\n\\nabstract contract BaseChain is Registrable, Ownable {\\n using ValueDecoder for bytes;\\n using ValueDecoder for uint224;\\n using MerkleProof for bytes32[];\\n\\n /// @param root merkle root for consensus\\n /// @param dataTimestamp consensus timestamp\\n struct Block {\\n bytes32 root;\\n uint32 dataTimestamp;\\n }\\n\\n /// @param value FCD value\\n /// @param dataTimestamp FCD timestamp\\n struct FirstClassData {\\n uint224 value;\\n uint32 dataTimestamp;\\n }\\n\\n /// @param blocksCountOffset number of all blocks that were generated before switching to this contract\\n /// @param sequence is a total number of blocks (consensus rounds) including previous contracts\\n /// @param lastTimestamp is a timestamp of last submitted block\\n /// @param padding number of seconds that need to pass before new submit will be possible\\n /// @param deprecated flag that changes to TRUE on `unregister`, when TRUE submissions are not longer available\\n struct ConsensusData {\\n uint32 blocksCountOffset;\\n uint32 sequence;\\n uint32 lastTimestamp;\\n uint32 padding;\\n bool deprecated;\\n }\\n\\n uint256 constant public VERSION = 2;\\n\\n bool internal immutable _ALLOW_FOR_MIXED_TYPE; // solhint-disable-line var-name-mixedcase\\n\\n bytes4 constant private _VERSION_SELECTOR = bytes4(keccak256(\\\"VERSION()\\\"));\\n\\n /// @dev minimal number of signatures required for accepting submission (PoA)\\n uint16 internal immutable _REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\\n\\n ConsensusData internal _consensusData;\\n\\n bytes constant public ETH_PREFIX = \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\";\\n\\n /// @dev block id (consensus ID) => root\\n /// consensus ID is at the same time consensus timestamp\\n mapping(uint256 => bytes32) public roots;\\n\\n /// @dev FCD key => FCD data\\n mapping(bytes32 => FirstClassData) public fcds;\\n\\n event LogDeprecation(address indexed deprecator);\\n event LogPadding(address indexed executor, uint32 timePadding);\\n\\n error ArraysDataDoNotMatch();\\n error AlreadyDeprecated();\\n error AlreadyRegistered();\\n error BlockSubmittedToFastOrDataToOld();\\n error ContractNotReady();\\n error FCDOverflow();\\n error InvalidContractType();\\n error NoChangeToState();\\n error OnlyOwnerOrRegistry();\\n error UnregisterFirst();\\n\\n modifier onlyOwnerOrRegistry () {\\n if (msg.sender != address(contractRegistry) && msg.sender != owner()) revert OnlyOwnerOrRegistry();\\n _;\\n }\\n\\n /// @param _contractRegistry Registry address\\n /// @param _padding required \\\"space\\\" between blocks in seconds\\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\\n constructor(\\n IRegistry _contractRegistry,\\n uint32 _padding,\\n uint16 _requiredSignatures,\\n bool _allowForMixedType\\n ) Registrable(_contractRegistry) {\\n _ALLOW_FOR_MIXED_TYPE = _allowForMixedType;\\n _REQUIRED_SIGNATURES = _requiredSignatures;\\n\\n _setPadding(_padding);\\n\\n BaseChain oldChain = BaseChain(_contractRegistry.getAddress(\\\"Chain\\\"));\\n\\n if (address(oldChain) == address(0)) {\\n // if this is first contract in sidechain, then we need to initialise lastTimestamp so submission\\n // can be possible\\n _consensusData.lastTimestamp = uint32(block.timestamp) - _padding - 1;\\n }\\n }\\n\\n /// @dev setter for `padding`\\n function setPadding(uint16 _padding) external {\\n _setPadding(_padding);\\n }\\n\\n /// @notice if this method needs to be called manually (not from Registry)\\n /// it is important to do it as part of tx batch\\n /// eg using multisig, we should prepare set of transactions and confirm them all at once\\n /// @inheritdoc Registrable\\n function register() external override onlyOwnerOrRegistry {\\n address oldChain = contractRegistry.getAddress(\\\"Chain\\\");\\n\\n // registration must be done before address in registry is replaced\\n if (oldChain == address(this)) revert AlreadyRegistered();\\n\\n if (oldChain == address(0x0)) {\\n return;\\n }\\n\\n _cloneLastDataFromPrevChain(oldChain);\\n }\\n\\n /// @inheritdoc Registrable\\n function unregister() external override onlyOwnerOrRegistry {\\n // in case we deprecated contract manually, we simply return\\n if (_consensusData.deprecated) return;\\n\\n address newChain = contractRegistry.getAddress(\\\"Chain\\\");\\n // unregistering must be done after address in registry is replaced\\n if (newChain == address(this)) revert UnregisterFirst();\\n\\n // TODO:\\n // I think we need to remove restriction for type (at least once)\\n // when we will switch to multichain architecture\\n\\n if (!_ALLOW_FOR_MIXED_TYPE) {\\n // can not be replaced with chain of different type\\n if (BaseChain(newChain).isForeign() != this.isForeign()) revert InvalidContractType();\\n }\\n\\n _consensusData.deprecated = true;\\n emit LogDeprecation(msg.sender);\\n }\\n\\n /// @notice it allows to deprecate contract manually\\n /// Only new Registry calls `unregister()` where we set deprecated to true\\n /// In old Registries we don't have this feature, so in order to safely redeploy new Chain\\n /// we will have to first deprecate current contract manually, then register new contract\\n function deprecate() external onlyOwnerOrRegistry {\\n if (_consensusData.deprecated) revert AlreadyDeprecated();\\n\\n _consensusData.deprecated = true;\\n emit LogDeprecation(msg.sender);\\n }\\n\\n /// @dev getter for `_consensusData`\\n function getConsensusData() external view returns (ConsensusData memory) {\\n return _consensusData;\\n }\\n\\n /// @dev number of blocks (consensus rounds) saved in this contract\\n function blocksCount() external view returns (uint256) {\\n return _consensusData.sequence - _consensusData.blocksCountOffset;\\n }\\n\\n function blocksCountOffset() external view returns (uint32) {\\n return _consensusData.blocksCountOffset;\\n }\\n\\n function lastBlockId() external view returns (uint256) {\\n return _consensusData.lastTimestamp;\\n }\\n\\n /// @return TRUE if contract is ForeignChain, FALSE otherwise\\n function isForeign() external pure virtual returns (bool);\\n\\n /// @inheritdoc Registrable\\n function getName() external pure override returns (bytes32) {\\n return \\\"Chain\\\";\\n }\\n\\n /// @param _affidavit root and FCDs hashed together\\n /// @param _v part of signature\\n /// @param _r part of signature\\n /// @param _s part of signature\\n /// @return signer address\\n function recoverSigner(bytes32 _affidavit, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _affidavit));\\n return ecrecover(hash, _v, _r, _s);\\n }\\n\\n /// @param _blockId ID of submitted block\\n /// @return block data (root + timestamp)\\n function blocks(uint256 _blockId) external view returns (Block memory) {\\n return Block(roots[_blockId], uint32(_blockId));\\n }\\n\\n /// @return current block ID\\n /// please note, that current ID is not the same as last ID, current means that once padding pass,\\n /// ID will switch to next one and it will be pointing to empty submit until submit for that ID is done\\n function getBlockId() external view returns (uint32) {\\n if (_consensusData.lastTimestamp == 0) return 0;\\n\\n return getBlockIdAtTimestamp(block.timestamp);\\n }\\n\\n function requiredSignatures() external view returns (uint16) {\\n return _REQUIRED_SIGNATURES;\\n }\\n\\n /// @dev calculates block ID for provided timestamp\\n /// this function does not works for past timestamps\\n /// @param _timestamp current or future timestamp\\n /// @return block ID for provided timestamp\\n function getBlockIdAtTimestamp(uint256 _timestamp) virtual public view returns (uint32) {\\n ConsensusData memory data = _consensusData;\\n\\n unchecked {\\n // we can't overflow because we adding two `uint32`\\n if (data.lastTimestamp + data.padding < _timestamp) {\\n return uint32(_timestamp);\\n }\\n }\\n\\n return data.lastTimestamp;\\n }\\n\\n /// @return last submitted block ID, please note, that on deployment, when there is no submission for this contract\\n /// block for last ID will be available in previous contract\\n function getLatestBlockId() virtual public view returns (uint32) {\\n return _consensusData.lastTimestamp;\\n }\\n\\n /// @dev verifies if the leaf is valid leaf for merkle tree\\n /// @param _proof merkle proof for merkle tree\\n /// @param _root merkle root\\n /// @param _leaf leaf hash\\n /// @return TRUE if `_leaf` is valid, FALSE otherwise\\n function verifyProof(bytes32[] memory _proof, bytes32 _root, bytes32 _leaf) public pure returns (bool) {\\n if (_root == bytes32(0)) {\\n return false;\\n }\\n\\n return _proof.verify(_root, _leaf);\\n }\\n\\n /// @dev creates leaf hash, that has is used in merkle tree\\n /// @param _key key under which we store the value\\n /// @param _value value itself as bytes\\n /// @return leaf hash\\n function hashLeaf(bytes memory _key, bytes memory _value) public pure returns (bytes32) {\\n return keccak256(abi.encodePacked(_key, _value));\\n }\\n\\n /// @dev verifies, if provided key-value pair was part of consensus\\n /// @param _blockId consensus ID for which we doing a check\\n /// @param _proof merkle proof for pair\\n /// @param _key pair key\\n /// @param _value pair value\\n /// @return TRUE if key-value par was part of consensus, FALSE otherwise\\n function verifyProofForBlock(\\n uint256 _blockId,\\n bytes32[] memory _proof,\\n bytes memory _key,\\n bytes memory _value\\n )\\n public\\n view\\n returns (bool)\\n {\\n return _proof.verify(roots[_blockId], keccak256(abi.encodePacked(_key, _value)));\\n }\\n\\n /// @dev this is helper method, that extracts one merkle proof from many hashed provided as bytes\\n /// @param _data many hashes as bytes\\n /// @param _offset this is starting point for extraction\\n /// @param _items how many hashes to extract\\n /// @return merkle proof (array of bytes32 hashes)\\n function bytesToBytes32Array(\\n bytes memory _data,\\n uint256 _offset,\\n uint256 _items\\n )\\n public\\n pure\\n returns (bytes32[] memory)\\n {\\n bytes32[] memory dataList = new bytes32[](_items);\\n\\n // we can unchecked because we working only with `i` and `_offset`\\n // in case of wrong `_offset` it will throw\\n unchecked {\\n for (uint256 i = 0; i < _items; i++) {\\n bytes32 temp;\\n uint256 idx = (i + 1 + _offset) * 32;\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n temp := mload(add(_data, idx))\\n }\\n\\n dataList[i] = temp;\\n }\\n }\\n\\n return (dataList);\\n }\\n\\n /// @dev batch method for data verification\\n /// @param _blockIds consensus IDs for which we doing a checks\\n /// @param _proofs merkle proofs for all pair, sequence of hashes provided as bytes\\n /// @param _proofItemsCounter array of counters, each counter tells how many hashes proof for each leaf has\\n /// @param _leaves array of merkle leaves\\n /// @return results array of verification results, TRUE if leaf is part of consensus, FALSE otherwise\\n function verifyProofs(\\n uint32[] memory _blockIds,\\n bytes memory _proofs,\\n uint256[] memory _proofItemsCounter,\\n bytes32[] memory _leaves\\n )\\n public\\n view\\n returns (bool[] memory results)\\n {\\n results = new bool[](_leaves.length);\\n uint256 offset = 0;\\n\\n for (uint256 i = 0; i < _leaves.length;) {\\n results[i] = bytesToBytes32Array(_proofs, offset, _proofItemsCounter[i]).verify(\\n roots[_blockIds[i]], _leaves[i]\\n );\\n\\n unchecked {\\n // we can uncheck because it will not overflow in a lifetime, and if someone provide invalid counter\\n // we verification will not be valid (or we throw because of invalid memory access)\\n offset += _proofItemsCounter[i];\\n // we can uncheck because `i` will not overflow in a lifetime\\n i++;\\n }\\n }\\n }\\n\\n /// @param _blockId consensus ID\\n /// @return root for provided consensus ID\\n function getBlockRoot(uint32 _blockId) external view returns (bytes32) {\\n return roots[_blockId];\\n }\\n\\n /// @param _blockId consensus ID\\n /// @return timestamp for provided consensus ID\\n function getBlockTimestamp(uint32 _blockId) external view returns (uint32) {\\n return roots[_blockId] == bytes32(0) ? 0 : _blockId;\\n }\\n\\n /// @dev batch getter for FCDs\\n /// @param _keys FCDs keys to fetch\\n /// @return values array of FCDs values\\n /// @return timestamps array of FCDs timestamps\\n function getCurrentValues(bytes32[] calldata _keys)\\n external\\n view\\n returns (uint256[] memory values, uint32[] memory timestamps)\\n {\\n timestamps = new uint32[](_keys.length);\\n values = new uint256[](_keys.length);\\n\\n for (uint i=0; i<_keys.length;) {\\n FirstClassData storage numericFCD = fcds[_keys[i]];\\n values[i] = uint256(numericFCD.value);\\n timestamps[i] = numericFCD.dataTimestamp;\\n\\n unchecked {\\n // we can uncheck because `i` will not overflow in a lifetime\\n i++;\\n }\\n }\\n }\\n\\n /// @dev getter for single FCD value\\n /// @param _key FCD key\\n /// @return value FCD value\\n /// @return timestamp FCD timestamp\\n function getCurrentValue(bytes32 _key) external view returns (uint256 value, uint256 timestamp) {\\n FirstClassData storage numericFCD = fcds[_key];\\n return (uint256(numericFCD.value), numericFCD.dataTimestamp);\\n }\\n\\n /// @dev getter for single FCD value in case its type is `int`\\n /// @param _key FCD key\\n /// @return value FCD value\\n /// @return timestamp FCD timestamp\\n function getCurrentIntValue(bytes32 _key) external view returns (int256 value, uint256 timestamp) {\\n FirstClassData storage numericFCD = fcds[_key];\\n return (numericFCD.value.toInt(), numericFCD.dataTimestamp);\\n }\\n\\n function _setPadding(uint32 _padding) internal onlyOwner {\\n if (_consensusData.padding == _padding) revert NoChangeToState();\\n\\n _consensusData.padding = _padding;\\n emit LogPadding(msg.sender, _padding);\\n }\\n\\n /// @dev we cloning last block time, because we will need reference point for next submissions\\n function _cloneLastDataFromPrevChain(address _prevChain) internal {\\n (bool success, bytes memory v) = _prevChain.staticcall(abi.encode(_VERSION_SELECTOR));\\n uint256 prevVersion = success ? abi.decode(v, (uint256)) : 1;\\n\\n if (prevVersion == 1) {\\n uint32 latestId = IBaseChainV1(address(_prevChain)).getLatestBlockId();\\n _consensusData.lastTimestamp = IBaseChainV1(address(_prevChain)).getBlockTimestamp(latestId);\\n\\n // +1 because getLatestBlockId subtracts 1\\n // +1 because it might be situation when tx is already in progress in old contract\\n // and old contract do not have deprecated flag\\n _consensusData.sequence = latestId + 2;\\n _consensusData.blocksCountOffset = latestId + 2;\\n } else { // VERSION 2\\n // with new Registry, we have register/unregister methods\\n // Chain will be deprecated, so there is no need to do \\\"+1\\\" as in old version\\n // TODO what with current Registries??\\n // we need a way to make it deprecated!\\n ConsensusData memory data = BaseChain(_prevChain).getConsensusData();\\n\\n _consensusData.sequence = data.sequence;\\n _consensusData.blocksCountOffset = data.sequence;\\n _consensusData.lastTimestamp = data.lastTimestamp;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcc7d655ad64f0a17cd71331260cf48828f0396e5e3b1428b6690c12f35a95db7\",\"license\":\"MIT\"},\"contracts/Chain.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./BaseChain.sol\\\";\\n\\ncontract Chain is BaseChain {\\n IStakingBank public immutable stakingBank;\\n\\n event LogMint(address indexed minter, uint256 blockId, uint256 staked, uint256 power);\\n event LogVoter(uint256 indexed blockId, address indexed voter, uint256 vote);\\n\\n error NotEnoughSignatures();\\n error SignaturesOutOfOrder();\\n\\n /// @param _contractRegistry Registry address\\n /// @param _padding required \\\"space\\\" between blocks in seconds\\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\\n /// @param _allowForMixedType we have two \\\"types\\\" of Chain: HomeChain and ForeignChain, when we redeploying\\n /// we don't want to mix up them, so we checking, if new Chain has the same type as current one.\\n /// However, when we will be switching from one homechain to another one, we have to allow for this mixing up.\\n /// This flag will tell contract, if this is the case.\\n constructor(\\n IRegistry _contractRegistry,\\n uint32 _padding,\\n uint16 _requiredSignatures,\\n bool _allowForMixedType\\n ) BaseChain(_contractRegistry, _padding, _requiredSignatures, _allowForMixedType) {\\n stakingBank = IStakingBank(_contractRegistry.requireAndGetAddress(\\\"StakingBank\\\"));\\n }\\n\\n /// @dev method for submitting consensus data\\n /// @param _dataTimestamp consensus timestamp, this is time for all data in merkle tree including FCDs\\n /// @param _root merkle root\\n /// @param _keys FCDs keys\\n /// @param _values FCDs values\\n /// @param _v array of `v` part of validators signatures\\n /// @param _r array of `r` part of validators signatures\\n /// @param _s array of `s` part of validators signatures\\n // solhint-disable-next-line function-max-lines, code-complexity\\n function submit(\\n uint32 _dataTimestamp,\\n bytes32 _root,\\n bytes32[] memory _keys,\\n uint256[] memory _values,\\n uint8[] memory _v,\\n bytes32[] memory _r,\\n bytes32[] memory _s\\n ) external {\\n // below two checks are only for pretty errors, so we can safe gas and allow for raw revert\\n // if (_keys.length != _values.length) revert ArraysDataDoNotMatch();\\n // if (_v.length != _r.length || _r.length != _s.length) revert ArraysDataDoNotMatch();\\n\\n _verifySubmitTimestampAndIncSequence(_dataTimestamp);\\n\\n // we can't expect minter will have exactly the same timestamp\\n // but for sure we can demand not to be off by a lot, that's why +3sec\\n // temporary remove this condition, because recently on ropsten we see cases when minter/node\\n // can be even 100sec behind\\n // require(_dataTimestamp <= block.timestamp + 3,\\n // string(abi.encodePacked(\\\"oh, so you can predict the future:\\\", _dataTimestamp - block.timestamp + 48)));\\n\\n bytes memory testimony = abi.encodePacked(_dataTimestamp, _root);\\n\\n for (uint256 i = 0; i < _keys.length;) {\\n if (uint224(_values[i]) != _values[i]) revert FCDOverflow();\\n\\n fcds[_keys[i]] = FirstClassData(uint224(_values[i]), _dataTimestamp);\\n testimony = abi.encodePacked(testimony, _keys[i], _values[i]);\\n\\n unchecked {\\n // we can't pass enough data to overflow\\n i++;\\n }\\n }\\n\\n uint256 signatures = 0;\\n uint256 power = 0;\\n //uint256 staked = stakingBank.totalSupply();\\n bytes32 affidavit = keccak256(testimony);\\n\\n address prevSigner = address(0x0);\\n\\n for (uint256 i; i < _v.length;) {\\n address signer = recoverSigner(affidavit, _v[i], _r[i], _s[i]);\\n uint256 balance = stakingBank.balanceOf(signer);\\n\\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\\n\\n prevSigner = signer;\\n\\n if (balance == 0) {\\n unchecked { i++; }\\n continue;\\n }\\n\\n signatures++;\\n emit LogVoter(uint256(_dataTimestamp), signer, balance);\\n\\n unchecked {\\n // we can't overflow because that means token overflowed\\n // and even if we do, we will get lower power\\n power += balance;\\n i++;\\n }\\n }\\n\\n if (signatures < _REQUIRED_SIGNATURES) revert NotEnoughSignatures();\\n\\n emit LogMint(msg.sender, _dataTimestamp, stakingBank.totalSupply(), power);\\n\\n // TODO remember to protect against flash loans when DPoS will be in place\\n // we turn on power once we have DPoS in action, we have PoA now\\n // require(power * 100 / staked >= 66, \\\"not enough power was gathered\\\");\\n\\n roots[_dataTimestamp] = _root;\\n _consensusData.lastTimestamp = _dataTimestamp;\\n }\\n\\n /// @inheritdoc BaseChain\\n function isForeign() external pure virtual override returns (bool) {\\n return false;\\n }\\n\\n /// @dev helper method that returns all important data about current state of contract\\n /// @return blockNumber `block.number`\\n /// @return timePadding `this.padding`\\n /// @return lastDataTimestamp timestamp for last submitted consensus\\n /// @return lastId ID of last submitted consensus\\n /// @return nextLeader leader for `block.timestamp + 1`\\n /// @return nextBlockId block ID for `block.timestamp + padding`\\n /// @return validators array of all validators addresses\\n /// @return powers array of all validators powers\\n /// @return locations array of all validators locations\\n /// @return staked total UMB staked by validators\\n /// @return minSignatures `this.requiredSignatures`\\n function getStatus() external view virtual returns(\\n uint256 blockNumber,\\n uint32 timePadding,\\n uint32 lastDataTimestamp,\\n uint32 lastId,\\n address nextLeader,\\n uint32 nextBlockId,\\n address[] memory validators,\\n uint256[] memory powers,\\n string[] memory locations,\\n uint256 staked,\\n uint16 minSignatures\\n ) {\\n ConsensusData memory data = _consensusData;\\n\\n blockNumber = block.number;\\n timePadding = data.padding;\\n lastId = data.lastTimestamp;\\n lastDataTimestamp = lastId;\\n minSignatures = _REQUIRED_SIGNATURES;\\n\\n staked = stakingBank.totalSupply();\\n uint256 numberOfValidators = stakingBank.getNumberOfValidators();\\n powers = new uint256[](numberOfValidators);\\n validators = new address[](numberOfValidators);\\n locations = new string[](numberOfValidators);\\n\\n for (uint256 i = 0; i < numberOfValidators;) {\\n validators[i] = stakingBank.addresses(i);\\n (, locations[i]) = stakingBank.validators(validators[i]);\\n powers[i] = stakingBank.balanceOf(validators[i]);\\n\\n unchecked {\\n // we will run out of gas before overflow happen\\n i++;\\n }\\n }\\n\\n unchecked {\\n // we will not overflow with timestamp in a lifetime\\n nextBlockId = lastId + data.padding + 1;\\n\\n nextLeader = numberOfValidators > 0\\n // we will not overflow with timestamp in a lifetime\\n ? validators[getLeaderIndex(numberOfValidators, block.timestamp + 1)]\\n : address(0);\\n }\\n }\\n\\n /// @return address of leader for next second\\n function getNextLeaderAddress() external view returns (address) {\\n return getLeaderAddressAtTime(block.timestamp + 1);\\n }\\n\\n /// @return address of current leader\\n function getLeaderAddress() external view returns (address) {\\n return getLeaderAddressAtTime(block.timestamp);\\n }\\n\\n /// @param _numberOfValidators total number of validators\\n /// @param _timestamp timestamp for which you want to calculate index\\n /// @return leader index, use it for StakingBank.addresses[index] to fetch leader address\\n function getLeaderIndex(uint256 _numberOfValidators, uint256 _timestamp) public view virtual returns (uint256) {\\n ConsensusData memory data = _consensusData;\\n\\n unchecked {\\n // we will not overflow on `timestamp` and `padding` in a life time\\n // timePadding + 1 => because padding is a space between blocks,\\n // so next round starts on first block after padding\\n // TODO will it work for off-chain??\\n uint256 validatorIndex = data.sequence + (_timestamp - data.lastTimestamp) / (data.padding + 1);\\n\\n return validatorIndex % _numberOfValidators;\\n }\\n }\\n\\n // @todo - properly handled non-enabled validators, newly added validators, and validators with low stake\\n /// @param _timestamp timestamp for which you want to calculate leader address\\n /// @return leader address for provider timestamp\\n function getLeaderAddressAtTime(uint256 _timestamp) public view virtual returns (address) {\\n uint256 numberOfValidators = stakingBank.getNumberOfValidators();\\n\\n if (numberOfValidators == 0) {\\n return address(0x0);\\n }\\n\\n uint256 validatorIndex = getLeaderIndex(numberOfValidators, _timestamp);\\n\\n return stakingBank.addresses(validatorIndex);\\n }\\n\\n /// @dev we had stack too deep in `submit` so this method was created as a solution\\n // we increasing `_consensusData.sequence` here so we don't have to read sequence again in other place\\n function _verifySubmitTimestampAndIncSequence(uint256 _dataTimestamp) internal {\\n ConsensusData memory data = _consensusData;\\n\\n // `data.lastTimestamp` must be setup either on deployment\\n // or via cloning from previous contract\\n if (data.lastTimestamp == 0) revert ContractNotReady();\\n\\n unchecked {\\n // we will not overflow with timestamp and padding in a life time\\n if (data.lastTimestamp + data.padding >= _dataTimestamp) revert BlockSubmittedToFastOrDataToOld();\\n }\\n\\n unchecked {\\n // we will not overflow in a life time\\n _consensusData.sequence = uint32(data.sequence + 1);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9eb872eaabac21d63c759e91507992710232a362afad6aa3221a8758d66f4e69\",\"license\":\"MIT\"},\"contracts/Registry.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\n// Inheritance\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport \\\"./extensions/Registrable.sol\\\";\\nimport \\\"./interfaces/IRegistry.sol\\\";\\n\\n/// @dev contracts registry\\n/// protocol uses this registry to fetch current contract addresses\\ncontract Registry is IRegistry, Ownable {\\n /// name => contract address\\n mapping(bytes32 => address) public registry;\\n\\n\\n error NameNotRegistered();\\n error ArraysDataDoNotMatch();\\n\\n /// @inheritdoc IRegistry\\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external onlyOwner {\\n if (_names.length != _destinations.length) revert ArraysDataDoNotMatch();\\n\\n for (uint i = 0; i < _names.length;) {\\n registry[_names[i]] = _destinations[i];\\n emit LogRegistered(_destinations[i], _names[i]);\\n\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @inheritdoc IRegistry\\n function importContracts(address[] calldata _destinations) external onlyOwner {\\n for (uint i = 0; i < _destinations.length;) {\\n bytes32 name = Registrable(_destinations[i]).getName();\\n registry[name] = _destinations[i];\\n emit LogRegistered(_destinations[i], name);\\n\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @inheritdoc IRegistry\\n function atomicUpdate(address _newContract) external onlyOwner {\\n Registrable(_newContract).register();\\n\\n bytes32 name = Registrable(_newContract).getName();\\n address oldContract = registry[name];\\n registry[name] = _newContract;\\n\\n Registrable(oldContract).unregister();\\n\\n emit LogRegistered(_newContract, name);\\n }\\n\\n /// @inheritdoc IRegistry\\n function requireAndGetAddress(bytes32 name) external view returns (address) {\\n address _foundAddress = registry[name];\\n if (_foundAddress == address(0)) revert NameNotRegistered();\\n\\n return _foundAddress;\\n }\\n\\n /// @inheritdoc IRegistry\\n function getAddress(bytes32 _bytes) external view returns (address) {\\n return registry[_bytes];\\n }\\n\\n /// @inheritdoc IRegistry\\n function getAddressByString(string memory _name) public view returns (address) {\\n return registry[stringToBytes32(_name)];\\n }\\n\\n /// @inheritdoc IRegistry\\n function stringToBytes32(string memory _string) public pure returns (bytes32 result) {\\n bytes memory tempEmptyStringTest = bytes(_string);\\n\\n if (tempEmptyStringTest.length == 0) {\\n return 0x0;\\n }\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n result := mload(add(_string, 32))\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcf8ac18bf5766420afcc70f34339192fa67169106ccdb51573267a1ffd95fb81\",\"license\":\"MIT\"},\"contracts/extensions/Registrable.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"../interfaces/IRegistry.sol\\\";\\nimport \\\"../interfaces/IStakingBank.sol\\\";\\n\\n/// @dev Any contract that we want to register in ContractRegistry, must inherit from Registrable\\nabstract contract Registrable {\\n IRegistry public immutable contractRegistry;\\n\\n modifier onlyFromContract(address _msgSender, bytes32 _contractName) {\\n require(\\n contractRegistry.getAddress(_contractName) == _msgSender,\\n string(abi.encodePacked(\\\"caller is not \\\", _contractName))\\n );\\n _;\\n }\\n\\n modifier withRegistrySetUp() {\\n require(address(contractRegistry) != address(0x0), \\\"_registry is empty\\\");\\n _;\\n }\\n\\n constructor(IRegistry _contractRegistry) {\\n require(address(_contractRegistry) != address(0x0), \\\"_registry is empty\\\");\\n contractRegistry = _contractRegistry;\\n }\\n\\n /// @dev this method will be called as a first method in registration process when old contract will be replaced\\n /// when called, old contract address is still in registry\\n function register() virtual external;\\n\\n /// @dev this method will be called as a last method in registration process when old contract will be replaced\\n /// when called, new contract address is already in registry\\n function unregister() virtual external;\\n\\n /// @return contract name as bytes32\\n function getName() virtual external pure returns (bytes32);\\n\\n /// @dev helper method for fetching StakingBank address\\n function stakingBankContract() public view returns (IStakingBank) {\\n return IStakingBank(contractRegistry.requireAndGetAddress(\\\"StakingBank\\\"));\\n }\\n\\n /// @dev helper method for fetching UMB address\\n function tokenContract() public view withRegistrySetUp returns (ERC20) {\\n return ERC20(contractRegistry.requireAndGetAddress(\\\"UMB\\\"));\\n }\\n}\\n\",\"keccak256\":\"0x58413fc819ff8f78ba80a9339bf6b4bb818932ddef0ce58dd4813acba01bda8c\",\"license\":\"MIT\"},\"contracts/interfaces/IBaseChainV1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IBaseChainV1 {\\n /// @dev number of blocks (consensus rounds) saved in this contract\\n function blocksCount() external returns (uint32);\\n\\n /// @dev number of all blocks that were generated before switching to this contract\\n /// please note, that there might be a gap of one block when we switching from old to new contract\\n /// see constructor for details\\n function blocksCountOffset() external returns (uint32);\\n\\n function getLatestBlockId() external view returns (uint32);\\n\\n function getBlockTimestamp(uint32 _blockId) external view returns (uint32);\\n\\n function getStatus() external view returns (\\n uint256 blockNumber,\\n uint16 timePadding,\\n uint32 lastDataTimestamp,\\n uint32 lastId,\\n uint32 nextBlockId\\n );\\n}\\n\",\"keccak256\":\"0x4196faa25b921cae447328983f172ee4289591b4136fdde54ad05552c559d371\",\"license\":\"MIT\"},\"contracts/interfaces/IRegistry.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\n\\ninterface IRegistry {\\n event LogRegistered(address indexed destination, bytes32 name);\\n\\n /// @dev imports new contract addresses and override old addresses, if they exist under provided name\\n /// This method can be used for contracts that for some reason do not have `getName` method\\n /// @param _names array of contract names that we want to register\\n /// @param _destinations array of contract addresses\\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external;\\n\\n /// @dev imports new contracts and override old addresses, if they exist.\\n /// Names of contracts are fetched directly from each contract by calling `getName`\\n /// @param _destinations array of contract addresses\\n function importContracts(address[] calldata _destinations) external;\\n\\n /// @dev this method ensure, that old and new contract is aware of it state in registry\\n /// Note: BSC registry does not have this method. This method was introduced in later stage.\\n /// @param _newContract address of contract that will replace old one\\n function atomicUpdate(address _newContract) external;\\n\\n /// @dev similar to `getAddress` but throws when contract name not exists\\n /// @param name contract name\\n /// @return contract address registered under provided name or throws, if does not exists\\n function requireAndGetAddress(bytes32 name) external view returns (address);\\n\\n /// @param name contract name in a form of bytes32\\n /// @return contract address registered under provided name\\n function getAddress(bytes32 name) external view returns (address);\\n\\n /// @param _name contract name\\n /// @return contract address assigned to the name or address(0) if not exists\\n function getAddressByString(string memory _name) external view returns (address);\\n\\n /// @dev helper method that converts string to bytes32,\\n /// you can use to to generate contract name\\n function stringToBytes32(string memory _string) external pure returns (bytes32 result);\\n}\\n\",\"keccak256\":\"0xa0099ecf4182138fda7a0733407784461410c245de67c1e7ba7cd7c9595e054f\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBank.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IStakingBank is IERC20 {\\n /// @param id address of validator wallet\\n /// @param location URL of the validator API\\n struct Validator {\\n address id;\\n string location;\\n }\\n\\n event LogValidatorRegistered(address indexed id);\\n event LogValidatorUpdated(address indexed id);\\n event LogValidatorRemoved(address indexed id);\\n event LogMinAmountForStake(uint256 minAmountForStake);\\n\\n /// @dev setter for `minAmountForStake`\\n function setMinAmountForStake(uint256 _minAmountForStake) external;\\n\\n /// @dev allows to stake `token` by validators\\n /// Validator needs to approve StakingBank beforehand\\n /// @param _value amount of tokens to stake\\n function stake(uint256 _value) external;\\n\\n /// @dev notification about approval from `_from` address on UMB token\\n /// Staking bank will stake max approved amount from `_from` address\\n /// @param _from address which approved token spend for IStakingBank\\n function receiveApproval(address _from) external returns (bool success);\\n\\n /// @dev withdraws stake tokens\\n /// it throws, when balance will be less than required minimum for stake\\n /// to withdraw all use `exit`\\n function withdraw(uint256 _value) external returns (bool success);\\n\\n /// @dev unstake and withdraw all tokens\\n function exit() external returns (bool success);\\n\\n /// @dev creates (register) new validator\\n /// @param _id validator address\\n /// @param _location location URL of the validator API\\n function create(address _id, string calldata _location) external;\\n\\n /// @dev removes validator\\n /// @param _id validator wallet\\n function remove(address _id) external;\\n\\n /// @dev updates validator location\\n /// @param _id validator wallet\\n /// @param _location new validator URL\\n function update(address _id, string calldata _location) external;\\n\\n /// @return total number of registered validators (with and without balance)\\n function getNumberOfValidators() external view returns (uint256);\\n\\n /// @dev gets validator address for provided index\\n /// @param _ix index in array of list of all validators wallets\\n function addresses(uint256 _ix) external view returns (address);\\n\\n /// @param _id address of validator\\n /// @return id address of validator\\n /// @return location URL of validator\\n function validators(address _id) external view returns (address id, string memory location);\\n}\\n\",\"keccak256\":\"0x2c518aeab8b0b3a364fafaec559d3ff0dc6a119f8d203fa31ef7ad667ca0f7b9\",\"license\":\"MIT\"}},\"version\":1}", "bytecode": "0x6101006040523480156200001257600080fd5b5060405162005e9138038062005e91833981810160405281019062000038919062000677565b8383838383600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603620000af576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620000a6906200074a565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250505062000104620000f8620002e660201b60201c565b620002ee60201b60201c565b80151560a0811515815250508161ffff1660c08161ffff16815250506200013183620003b260201b60201c565b60008473ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b81526004016200016c9062000792565b602060405180830381865afa1580156200018a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001b09190620007de565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603620002275760018442620001f791906200083f565b6200020391906200083f565b600160000160086101000a81548163ffffffff021916908363ffffffff1602179055505b50505050508373ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b81526004016200026590620008a0565b602060405180830381865afa15801562000283573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002a99190620007de565b73ffffffffffffffffffffffffffffffffffffffff1660e08173ffffffffffffffffffffffffffffffffffffffff1681525050505050506200095b565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b620003c2620002e660201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16620003e86200051360201b60201c565b73ffffffffffffffffffffffffffffffffffffffff161462000441576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000438906200090b565b60405180910390fd5b8063ffffffff166001600001600c9054906101000a900463ffffffff1663ffffffff16036200049c576040517f96f56f6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600001600c6101000a81548163ffffffff021916908363ffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167f02ff77a0f68d11f7efb906f331b2dda82916de8ba9c37dda2a95817936a530ec826040516200050891906200093e565b60405180910390a250565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200056e8262000541565b9050919050565b6000620005828262000561565b9050919050565b620005948162000575565b8114620005a057600080fd5b50565b600081519050620005b48162000589565b92915050565b600063ffffffff82169050919050565b620005d581620005ba565b8114620005e157600080fd5b50565b600081519050620005f581620005ca565b92915050565b600061ffff82169050919050565b6200061481620005fb565b81146200062057600080fd5b50565b600081519050620006348162000609565b92915050565b60008115159050919050565b62000651816200063a565b81146200065d57600080fd5b50565b600081519050620006718162000646565b92915050565b600080600080608085870312156200069457620006936200053c565b5b6000620006a487828801620005a3565b9450506020620006b787828801620005e4565b9350506040620006ca8782880162000623565b9250506060620006dd8782880162000660565b91505092959194509250565b600082825260208201905092915050565b7f5f726567697374727920697320656d7074790000000000000000000000000000600082015250565b600062000732601283620006e9565b91506200073f82620006fa565b602082019050919050565b60006020820190508181036000830152620007658162000723565b9050919050565b7f436861696e000000000000000000000000000000000000000000000000000000815250565b6000602082019050620007a8600083016200076c565b919050565b620007b88162000561565b8114620007c457600080fd5b50565b600081519050620007d881620007ad565b92915050565b600060208284031215620007f757620007f66200053c565b5b60006200080784828501620007c7565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006200084c82620005ba565b91506200085983620005ba565b9250828210156200086f576200086e62000810565b5b828203905092915050565b7f5374616b696e6742616e6b000000000000000000000000000000000000000000815250565b6000602082019050620008b6600083016200087a565b919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000620008f3602083620006e9565b91506200090082620008bb565b602082019050919050565b600060208201905081810360008301526200092681620008e4565b9050919050565b6200093881620005ba565b82525050565b60006020820190506200095560008301846200092d565b92915050565b60805160a05160c05160e05161547762000a1a60003960008181610eac0152818161122601528181611451015281816116880152818161171b0152818161189d0152818161198401528181611a5d0152818161291901526129ca0152600081816113ba015281816116650152611f410152600061276301526000818161082701528181610a1d01528181610ae501528181611bab01528181611c2201528181611cc10152818161207901528181612585015261266401526154776000f3fe608060405234801561001057600080fd5b50600436106101f95760003560e01c80630f2acc3e146101fe5780630fcc0c281461022e57806317d7de7c14610238578063199dadc5146102565780631aa3a00814610286578063243b68f91461029057806324c89a49146102c057806326f3ab8b146102de57806334ba34811461030f5780633bb8819d1461032d57806340a9e5e31461035e578063485e055d1461037a5780634bc935d7146103965780634e69d560146103c657806355a373d6146103ee578063637180a81461040c5780636d046c3e1461042a578063715018a6146104485780637353cbcb1461045257806377839fe614610470578063805d34321461048e5780638d068043146104be5780638da5cb5b146104dc5780639f6119d7146104fa578063a0bc937414610518578063abf410e514610536578063adf1639d14610554578063bef9f8a114610585578063bf66e3ba146105b5578063c2a4250b146105e5578063c2b40ae414610603578063c3369db814610633578063ca4d29d214610663578063cbb1b2c714610693578063d3d3ea08146106c4578063d45167d0146106e2578063e76c0b5714610712578063e79a198f14610730578063ed9975c31461073a578063ef19f3e714610758578063f25b3f9914610788578063f2fde38b146107b8578063ffa1ad74146107d4575b600080fd5b6102186004803603810190610213919061358f565b6107f2565b6040516102259190613620565b60405180910390f35b610236610825565b005b610240610997565b60405161024d9190613620565b60405180910390f35b610270600480360381019061026b9190613765565b6109bf565b60405161027d919061383b565b60405180910390f35b61028e610a1b565b005b6102aa60048036038101906102a59190613856565b610c29565b6040516102b79190613983565b60405180910390f35b6102c8610cd2565b6040516102d59190613a2d565b60405180910390f35b6102f860048036038101906102f39190613aaa565b610d0b565b604051610306929190613c83565b60405180910390f35b610317610eaa565b6040516103249190613d39565b60405180910390f35b61034760048036038101906103429190613d54565b610ece565b604051610355929190613da9565b60405180910390f35b61037860048036038101906103739190613e0c565b610f63565b005b610394600480360381019061038f9190614024565b610f73565b005b6103b060048036038101906103ab9190614152565b611546565b6040516103bd919061383b565b60405180910390f35b6103ce61157a565b6040516103e59b9a999897969594939291906143d5565b60405180910390f35b6103f6611b90565b60405161040391906144b6565b60405180910390f35b610414611cbd565b6040516104219190613d39565b60405180910390f35b610432611d5c565b60405161043f919061383b565b60405180910390f35b610450611d61565b005b61045a611de9565b60405161046791906144d1565b60405180910390f35b610478611e2c565b60405161048591906144ec565b60405180910390f35b6104a860048036038101906104a39190614507565b611e49565b6040516104b591906144ec565b60405180910390f35b6104c6611f3d565b6040516104d39190614534565b60405180910390f35b6104e4611f65565b6040516104f1919061454f565b60405180910390f35b610502611f8e565b60405161050f919061454f565b60405180910390f35b610520611faa565b60405161052d91906145e1565b60405180910390f35b61053e612077565b60405161054b919061461d565b60405180910390f35b61056e60048036038101906105699190613d54565b61209b565b60405161057c929190614638565b60405180910390f35b61059f600480360381019061059a9190614661565b612128565b6040516105ac9190613620565b60405180910390f35b6105cf60048036038101906105ca9190614751565b61214b565b6040516105dc91906148d7565b60405180910390f35b6105ed612287565b6040516105fa91906144d1565b60405180910390f35b61061d60048036038101906106189190614507565b6122aa565b60405161062a9190613620565b60405180910390f35b61064d60048036038101906106489190614661565b6122c2565b60405161065a91906144ec565b60405180910390f35b61067d600480360381019061067891906148f9565b6122f7565b60405161068a91906144d1565b60405180910390f35b6106ad60048036038101906106a89190613d54565b612411565b6040516106bb929190614970565b60405180910390f35b6106cc61246d565b6040516106d991906144ec565b60405180910390f35b6106fc60048036038101906106f79190614999565b61248a565b604051610709919061454f565b60405180910390f35b61071a612547565b60405161072791906144ec565b60405180910390f35b610738612583565b005b610742612904565b60405161074f919061454f565b60405180910390f35b610772600480360381019061076d9190614507565b612914565b60405161077f919061454f565b60405180910390f35b6107a2600480360381019061079d9190614507565b612a6c565b6040516107af9190614a2f565b60405180910390f35b6107d260048036038101906107cd9190614a76565b612aa9565b005b6107dc612ba0565b6040516107e991906144d1565b60405180910390f35b60008282604051602001610807929190614adf565b60405160208183030381529060405280519060200120905092915050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156108b45750610884611f65565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156108eb576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160000160109054906101000a900460ff1615610935576040517f764c143b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018060000160106101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167fd4ae81319f0b4df100dcda9ce971671b97278c7a5ce6b37a8331a44700679fd460405160405180910390a2565b60007f436861696e000000000000000000000000000000000000000000000000000000905090565b6000610a11600260008781526020019081526020016000205484846040516020016109eb929190614adf565b6040516020818303038152906040528051906020012086612ba59092919063ffffffff16565b9050949350505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015610aaa5750610a7a611f65565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15610ae1576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b8152600401610b3a90614b29565b602060405180830381865afa158015610b57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7b9190614b57565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610be2576040517f3a81d6fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610c1c5750610c27565b610c2581612bbc565b505b565b606060008267ffffffffffffffff811115610c4757610c46613464565b5b604051908082528060200260200182016040528015610c755781602001602082028036833780820191505090505b50905060005b83811015610cc657600080602087600185010102905080880151915081848481518110610cab57610caa614b84565b5b60200260200101818152505050508080600101915050610c7b565b50809150509392505050565b6040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525081565b6060808383905067ffffffffffffffff811115610d2b57610d2a613464565b5b604051908082528060200260200182016040528015610d595781602001602082028036833780820191505090505b5090508383905067ffffffffffffffff811115610d7957610d78613464565b5b604051908082528060200260200182016040528015610da75781602001602082028036833780820191505090505b50915060005b84849050811015610ea257600060036000878785818110610dd157610dd0614b84565b5b90506020020135815260200190815260200160002090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16848381518110610e4657610e45614b84565b5b60200260200101818152505080600001601c9054906101000a900463ffffffff16838381518110610e7a57610e79614b84565b5b602002602001019063ffffffff16908163ffffffff1681525050818060010192505050610dad565b509250929050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806000600360008581526020019081526020016000209050610f3b8160000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16612efe565b81600001601c9054906101000a900463ffffffff168063ffffffff1690509250925050915091565b610f708161ffff16612fa6565b50565b610f828763ffffffff166130f1565b60008787604051602001610f97929190614c0a565b604051602081830303815290604052905060005b86518110156111a757858181518110610fc757610fc6614b84565b5b6020026020010151868281518110610fe257610fe1614b84565b5b60200260200101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff161461103f576040517f6980091000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604051806040016040528087838151811061105d5761105c614b84565b5b60200260200101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681526020018a63ffffffff16815250600360008984815181106110a9576110a8614b84565b5b6020026020010151815260200190815260200160002060008201518160000160006101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff160217905550602082015181600001601c6101000a81548163ffffffff021916908363ffffffff1602179055509050508187828151811061115457611153614b84565b5b602002602001015187838151811061116f5761116e614b84565b5b602002602001015160405160200161118993929190614c57565b60405160208183030381529060405291508080600101915050610fab565b506000806000838051906020012090506000805b88518110156113b7576000611220848b84815181106111dd576111dc614b84565b5b60200260200101518b85815181106111f8576111f7614b84565b5b60200260200101518b868151811061121357611212614b84565b5b602002602001015161248a565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231836040518263ffffffff1660e01b815260040161127d919061454f565b602060405180830381865afa15801561129a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112be9190614ca5565b90508173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1610611325576040517f9079f69b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8193506000810361133f57828060010193505050506113b2565b868061134a90614d01565b9750508173ffffffffffffffffffffffffffffffffffffffff168f63ffffffff167fbac7552ab5da8d0588709ddb75aceec28520646f54bca1cc5e6e104db61935ec8360405161139a91906144d1565b60405180910390a38086019550828060010193505050505b6111bb565b507f000000000000000000000000000000000000000000000000000000000000000061ffff16841015611416576040517fe246dc6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167f5f11830295067c4bcc7d02d4e3b048cd7427be50a3aeb6afc9d3d559ee64bcfa8d7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114de9190614ca5565b866040516114ee93929190614d7a565b60405180910390a28a600260008e63ffffffff168152602001908152602001600020819055508b600160000160086101000a81548163ffffffff021916908363ffffffff160217905550505050505050505050505050565b60008060001b830361155b5760009050611573565b611570838386612ba59092919063ffffffff16565b90505b9392505050565b6000806000806000806060806060600080600060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff1615151515815250509050439b5080606001519a50806040015198508899507f000000000000000000000000000000000000000000000000000000000000000091507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117159190614ca5565b925060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16639031d9136040518163ffffffff1660e01b8152600401602060405180830381865afa158015611784573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a89190614ca5565b90508067ffffffffffffffff8111156117c4576117c3613464565b5b6040519080825280602002602001820160405280156117f25781602001602082028036833780820191505090505b5095508067ffffffffffffffff81111561180f5761180e613464565b5b60405190808252806020026020018201604052801561183d5781602001602082028036833780820191505090505b5096508067ffffffffffffffff81111561185a57611859613464565b5b60405190808252806020026020018201604052801561188d57816020015b60608152602001906001900390816118785790505b50945060005b81811015611b3b577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663edf26d9b826040518263ffffffff1660e01b81526004016118f491906144d1565b602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119359190614b57565b88828151811061194857611947614b84565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663fa52c7d88983815181106119d1576119d0614b84565b5b60200260200101516040518263ffffffff1660e01b81526004016119f5919061454f565b600060405180830381865afa158015611a12573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611a3b9190614e52565b9050868281518110611a5057611a4f614b84565b5b60200260200101819052507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231898381518110611aaa57611aa9614b84565b5b60200260200101516040518263ffffffff1660e01b8152600401611ace919061454f565b602060405180830381865afa158015611aeb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0f9190614ca5565b878281518110611b2257611b21614b84565b5b6020026020010181815250508080600101915050611893565b50600182606001518b0101975060008111611b57576000611b7f565b86611b6582600142016122f7565b81518110611b7657611b75614b84565b5b60200260200101515b98505050909192939495969798999a565b60008073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1603611c20576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c1790614f0b565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b8152600401611c7790614f51565b602060405180830381865afa158015611c94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cb89190614b57565b905090565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b8152600401611d1690614f90565b602060405180830381865afa158015611d33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d579190614b57565b905090565b600090565b611d69613271565b73ffffffffffffffffffffffffffffffffffffffff16611d87611f65565b73ffffffffffffffffffffffffffffffffffffffff1614611ddd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dd490614ff5565b60405180910390fd5b611de76000613279565b565b6000600160000160009054906101000a900463ffffffff16600160000160049054906101000a900463ffffffff16611e219190615015565b63ffffffff16905090565b6000600160000160009054906101000a900463ffffffff16905090565b60008060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff161515151581525050905082816060015182604001510163ffffffff161015611f2f5782915050611f38565b80604001519150505b919050565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000611fa5600142611fa09190615049565b612914565b905090565b611fb26133c9565b60016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff161515151581525050905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060006003600085815260200190815260200160002090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681600001601c9054906101000a900463ffffffff168063ffffffff1690509250925050915091565b6000600260008363ffffffff168152602001908152602001600020549050919050565b6060815167ffffffffffffffff81111561216857612167613464565b5b6040519080825280602002602001820160405280156121965781602001602082028036833780820191505090505b5090506000805b835181101561227d5761222c600260008984815181106121c0576121bf614b84565b5b602002602001015163ffffffff168152602001908152602001600020548583815181106121f0576121ef614b84565b5b602002602001015161221d89868a87815181106122105761220f614b84565b5b6020026020010151610c29565b612ba59092919063ffffffff16565b83828151811061223f5761223e614b84565b5b60200260200101901515908115158152505084818151811061226457612263614b84565b5b602002602001015182019150808060010191505061219d565b5050949350505050565b6000600160000160089054906101000a900463ffffffff1663ffffffff16905090565b60026020528060005260406000206000915090505481565b60008060001b600260008463ffffffff16815260200190815260200160002054146122ed57816122f0565b60005b9050919050565b60008060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff16151515158152505090506000600182606001510163ffffffff16826040015163ffffffff168503816123e7576123e661509f565b5b04826020015163ffffffff160190508481816124065761240561509f565b5b069250505092915050565b60036020528060005260406000206000915090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169080600001601c9054906101000a900463ffffffff16905082565b6000600160000160089054906101000a900463ffffffff16905090565b6000806040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250866040516020016124d59291906150ce565b604051602081830303815290604052805190602001209050600181868686604051600081526020016040526040516125109493929190615105565b6020604051602081039080840390855afa158015612532573d6000803e3d6000fd5b50505060206040510351915050949350505050565b600080600160000160089054906101000a900463ffffffff1663ffffffff16036125745760009050612580565b61257d42611e49565b90505b90565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415801561261257506125e2611f65565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15612649576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160000160109054906101000a900460ff166129025760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b81526004016126b990614b29565b602060405180830381865afa1580156126d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fa9190614b57565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612761576040517ff8e0084400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006128a0573073ffffffffffffffffffffffffffffffffffffffff16636d046c3e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f59190615176565b15158173ffffffffffffffffffffffffffffffffffffffff16636d046c3e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612842573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128669190615176565b15151461289f576040517f07b72f5e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b60018060000160106101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167fd4ae81319f0b4df100dcda9ce971671b97278c7a5ce6b37a8331a44700679fd460405160405180910390a2505b565b600061290f42612914565b905090565b6000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16639031d9136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612982573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129a69190614ca5565b9050600081036129ba576000915050612a67565b60006129c682856122f7565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663edf26d9b826040518263ffffffff1660e01b8152600401612a2191906144d1565b602060405180830381865afa158015612a3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a629190614b57565b925050505b919050565b612a74613412565b6040518060400160405280600260008581526020019081526020016000205481526020018363ffffffff168152509050919050565b612ab1613271565b73ffffffffffffffffffffffffffffffffffffffff16612acf611f65565b73ffffffffffffffffffffffffffffffffffffffff1614612b25576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b1c90614ff5565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612b94576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b8b90615215565b60405180910390fd5b612b9d81613279565b50565b600281565b600082612bb2858461333d565b1490509392505050565b6000808273ffffffffffffffffffffffffffffffffffffffff167fffa1ad74ba96b4c159a84d090433911c3991c54f629eb60d0c84aed3be5f067c604051602001612c079190615270565b604051602081830303815290604052604051612c23919061528b565b600060405180830381855afa9150503d8060008114612c5e576040519150601f19603f3d011682016040523d82523d6000602084013e612c63565b606091505b5091509150600082612c76576001612c8b565b81806020019051810190612c8a9190614ca5565b5b905060018103612e0b5760008473ffffffffffffffffffffffffffffffffffffffff1663d3d3ea086040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ce2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d0691906152b7565b90508473ffffffffffffffffffffffffffffffffffffffff1663c3369db8826040518263ffffffff1660e01b8152600401612d4191906144ec565b602060405180830381865afa158015612d5e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d8291906152b7565b600160000160086101000a81548163ffffffff021916908363ffffffff160217905550600281612db291906152e4565b600160000160046101000a81548163ffffffff021916908363ffffffff160217905550600281612de291906152e4565b600160000160006101000a81548163ffffffff021916908363ffffffff16021790555050612ef8565b60008473ffffffffffffffffffffffffffffffffffffffff1663a0bc93746040518163ffffffff1660e01b815260040160a060405180830381865afa158015612e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e7c91906153af565b90508060200151600160000160046101000a81548163ffffffff021916908363ffffffff1602179055508060200151600160000160006101000a81548163ffffffff021916908363ffffffff1602179055508060400151600160000160086101000a81548163ffffffff021916908363ffffffff160217905550505b50505050565b60008060007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90506002600182612f3191906153dc565b612f3b9190615410565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1611612f905760008401915081601b0b92505050612fa1565b600181850303915081601b0b925050505b919050565b612fae613271565b73ffffffffffffffffffffffffffffffffffffffff16612fcc611f65565b73ffffffffffffffffffffffffffffffffffffffff1614613022576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161301990614ff5565b60405180910390fd5b8063ffffffff166001600001600c9054906101000a900463ffffffff1663ffffffff160361307c576040517f96f56f6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600001600c6101000a81548163ffffffff021916908363ffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167f02ff77a0f68d11f7efb906f331b2dda82916de8ba9c37dda2a95817936a530ec826040516130e691906144ec565b60405180910390a250565b600060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff16151515158152505090506000816040015163ffffffff16036131f9576040517f96a96e1700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81816060015182604001510163ffffffff1610613242576040517ff886149e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001816020015101600160000160046101000a81548163ffffffff021916908363ffffffff1602179055505050565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60008082905060005b84518110156133a757600085828151811061336457613363614b84565b5b602002602001015190508083116133865761337f83826133b2565b9250613393565b61339081846133b2565b92505b50808061339f90614d01565b915050613346565b508091505092915050565b600082600052816020526040600020905092915050565b6040518060a00160405280600063ffffffff168152602001600063ffffffff168152602001600063ffffffff168152602001600063ffffffff1681526020016000151581525090565b604051806040016040528060008019168152602001600063ffffffff1681525090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61349c82613453565b810181811067ffffffffffffffff821117156134bb576134ba613464565b5b80604052505050565b60006134ce613435565b90506134da8282613493565b919050565b600067ffffffffffffffff8211156134fa576134f9613464565b5b61350382613453565b9050602081019050919050565b82818337600083830152505050565b600061353261352d846134df565b6134c4565b90508281526020810184848401111561354e5761354d61344e565b5b613559848285613510565b509392505050565b600082601f83011261357657613575613449565b5b813561358684826020860161351f565b91505092915050565b600080604083850312156135a6576135a561343f565b5b600083013567ffffffffffffffff8111156135c4576135c3613444565b5b6135d085828601613561565b925050602083013567ffffffffffffffff8111156135f1576135f0613444565b5b6135fd85828601613561565b9150509250929050565b6000819050919050565b61361a81613607565b82525050565b60006020820190506136356000830184613611565b92915050565b6000819050919050565b61364e8161363b565b811461365957600080fd5b50565b60008135905061366b81613645565b92915050565b600067ffffffffffffffff82111561368c5761368b613464565b5b602082029050602081019050919050565b600080fd5b6136ab81613607565b81146136b657600080fd5b50565b6000813590506136c8816136a2565b92915050565b60006136e16136dc84613671565b6134c4565b905080838252602082019050602084028301858111156137045761370361369d565b5b835b8181101561372d578061371988826136b9565b845260208401935050602081019050613706565b5050509392505050565b600082601f83011261374c5761374b613449565b5b813561375c8482602086016136ce565b91505092915050565b6000806000806080858703121561377f5761377e61343f565b5b600061378d8782880161365c565b945050602085013567ffffffffffffffff8111156137ae576137ad613444565b5b6137ba87828801613737565b935050604085013567ffffffffffffffff8111156137db576137da613444565b5b6137e787828801613561565b925050606085013567ffffffffffffffff81111561380857613807613444565b5b61381487828801613561565b91505092959194509250565b60008115159050919050565b61383581613820565b82525050565b6000602082019050613850600083018461382c565b92915050565b60008060006060848603121561386f5761386e61343f565b5b600084013567ffffffffffffffff81111561388d5761388c613444565b5b61389986828701613561565b93505060206138aa8682870161365c565b92505060406138bb8682870161365c565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6138fa81613607565b82525050565b600061390c83836138f1565b60208301905092915050565b6000602082019050919050565b6000613930826138c5565b61393a81856138d0565b9350613945836138e1565b8060005b8381101561397657815161395d8882613900565b975061396883613918565b925050600181019050613949565b5085935050505092915050565b6000602082019050818103600083015261399d8184613925565b905092915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156139df5780820151818401526020810190506139c4565b838111156139ee576000848401525b50505050565b60006139ff826139a5565b613a0981856139b0565b9350613a198185602086016139c1565b613a2281613453565b840191505092915050565b60006020820190508181036000830152613a4781846139f4565b905092915050565b600080fd5b60008083601f840112613a6a57613a69613449565b5b8235905067ffffffffffffffff811115613a8757613a86613a4f565b5b602083019150836020820283011115613aa357613aa261369d565b5b9250929050565b60008060208385031215613ac157613ac061343f565b5b600083013567ffffffffffffffff811115613adf57613ade613444565b5b613aeb85828601613a54565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b613b2c8161363b565b82525050565b6000613b3e8383613b23565b60208301905092915050565b6000602082019050919050565b6000613b6282613af7565b613b6c8185613b02565b9350613b7783613b13565b8060005b83811015613ba8578151613b8f8882613b32565b9750613b9a83613b4a565b925050600181019050613b7b565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600063ffffffff82169050919050565b613bfa81613be1565b82525050565b6000613c0c8383613bf1565b60208301905092915050565b6000602082019050919050565b6000613c3082613bb5565b613c3a8185613bc0565b9350613c4583613bd1565b8060005b83811015613c76578151613c5d8882613c00565b9750613c6883613c18565b925050600181019050613c49565b5085935050505092915050565b60006040820190508181036000830152613c9d8185613b57565b90508181036020830152613cb18184613c25565b90509392505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000613cff613cfa613cf584613cba565b613cda565b613cba565b9050919050565b6000613d1182613ce4565b9050919050565b6000613d2382613d06565b9050919050565b613d3381613d18565b82525050565b6000602082019050613d4e6000830184613d2a565b92915050565b600060208284031215613d6a57613d6961343f565b5b6000613d78848285016136b9565b91505092915050565b6000819050919050565b613d9481613d81565b82525050565b613da38161363b565b82525050565b6000604082019050613dbe6000830185613d8b565b613dcb6020830184613d9a565b9392505050565b600061ffff82169050919050565b613de981613dd2565b8114613df457600080fd5b50565b600081359050613e0681613de0565b92915050565b600060208284031215613e2257613e2161343f565b5b6000613e3084828501613df7565b91505092915050565b613e4281613be1565b8114613e4d57600080fd5b50565b600081359050613e5f81613e39565b92915050565b600067ffffffffffffffff821115613e8057613e7f613464565b5b602082029050602081019050919050565b6000613ea4613e9f84613e65565b6134c4565b90508083825260208201905060208402830185811115613ec757613ec661369d565b5b835b81811015613ef05780613edc888261365c565b845260208401935050602081019050613ec9565b5050509392505050565b600082601f830112613f0f57613f0e613449565b5b8135613f1f848260208601613e91565b91505092915050565b600067ffffffffffffffff821115613f4357613f42613464565b5b602082029050602081019050919050565b600060ff82169050919050565b613f6a81613f54565b8114613f7557600080fd5b50565b600081359050613f8781613f61565b92915050565b6000613fa0613f9b84613f28565b6134c4565b90508083825260208201905060208402830185811115613fc357613fc261369d565b5b835b81811015613fec5780613fd88882613f78565b845260208401935050602081019050613fc5565b5050509392505050565b600082601f83011261400b5761400a613449565b5b813561401b848260208601613f8d565b91505092915050565b600080600080600080600060e0888a0312156140435761404261343f565b5b60006140518a828b01613e50565b97505060206140628a828b016136b9565b965050604088013567ffffffffffffffff81111561408357614082613444565b5b61408f8a828b01613737565b955050606088013567ffffffffffffffff8111156140b0576140af613444565b5b6140bc8a828b01613efa565b945050608088013567ffffffffffffffff8111156140dd576140dc613444565b5b6140e98a828b01613ff6565b93505060a088013567ffffffffffffffff81111561410a57614109613444565b5b6141168a828b01613737565b92505060c088013567ffffffffffffffff81111561413757614136613444565b5b6141438a828b01613737565b91505092959891949750929550565b60008060006060848603121561416b5761416a61343f565b5b600084013567ffffffffffffffff81111561418957614188613444565b5b61419586828701613737565b93505060206141a6868287016136b9565b92505060406141b7868287016136b9565b9150509250925092565b6141ca81613be1565b82525050565b60006141db82613cba565b9050919050565b6141eb816141d0565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b614226816141d0565b82525050565b6000614238838361421d565b60208301905092915050565b6000602082019050919050565b600061425c826141f1565b61426681856141fc565b93506142718361420d565b8060005b838110156142a2578151614289888261422c565b975061429483614244565b925050600181019050614275565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b6000614302826142db565b61430c81856142e6565b935061431c8185602086016139c1565b61432581613453565b840191505092915050565b600061433c83836142f7565b905092915050565b6000602082019050919050565b600061435c826142af565b61436681856142ba565b935083602082028501614378856142cb565b8060005b858110156143b457848403895281516143958582614330565b94506143a083614344565b925060208a0199505060018101905061437c565b50829750879550505050505092915050565b6143cf81613dd2565b82525050565b6000610160820190506143eb600083018e613d9a565b6143f8602083018d6141c1565b614405604083018c6141c1565b614412606083018b6141c1565b61441f608083018a6141e2565b61442c60a08301896141c1565b81810360c083015261443e8188614251565b905081810360e08301526144528187613b57565b90508181036101008301526144678186614351565b9050614477610120830185613d9a565b6144856101408301846143c6565b9c9b505050505050505050505050565b60006144a082613d06565b9050919050565b6144b081614495565b82525050565b60006020820190506144cb60008301846144a7565b92915050565b60006020820190506144e66000830184613d9a565b92915050565b600060208201905061450160008301846141c1565b92915050565b60006020828403121561451d5761451c61343f565b5b600061452b8482850161365c565b91505092915050565b600060208201905061454960008301846143c6565b92915050565b600060208201905061456460008301846141e2565b92915050565b61457381613820565b82525050565b60a08201600082015161458f6000850182613bf1565b5060208201516145a26020850182613bf1565b5060408201516145b56040850182613bf1565b5060608201516145c86060850182613bf1565b5060808201516145db608085018261456a565b50505050565b600060a0820190506145f66000830184614579565b92915050565b600061460782613d06565b9050919050565b614617816145fc565b82525050565b6000602082019050614632600083018461460e565b92915050565b600060408201905061464d6000830185613d9a565b61465a6020830184613d9a565b9392505050565b6000602082840312156146775761467661343f565b5b600061468584828501613e50565b91505092915050565b600067ffffffffffffffff8211156146a9576146a8613464565b5b602082029050602081019050919050565b60006146cd6146c88461468e565b6134c4565b905080838252602082019050602084028301858111156146f0576146ef61369d565b5b835b8181101561471957806147058882613e50565b8452602084019350506020810190506146f2565b5050509392505050565b600082601f83011261473857614737613449565b5b81356147488482602086016146ba565b91505092915050565b6000806000806080858703121561476b5761476a61343f565b5b600085013567ffffffffffffffff81111561478957614788613444565b5b61479587828801614723565b945050602085013567ffffffffffffffff8111156147b6576147b5613444565b5b6147c287828801613561565b935050604085013567ffffffffffffffff8111156147e3576147e2613444565b5b6147ef87828801613efa565b925050606085013567ffffffffffffffff8111156148105761480f613444565b5b61481c87828801613737565b91505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000614860838361456a565b60208301905092915050565b6000602082019050919050565b600061488482614828565b61488e8185614833565b935061489983614844565b8060005b838110156148ca5781516148b18882614854565b97506148bc8361486c565b92505060018101905061489d565b5085935050505092915050565b600060208201905081810360008301526148f18184614879565b905092915050565b600080604083850312156149105761490f61343f565b5b600061491e8582860161365c565b925050602061492f8582860161365c565b9150509250929050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff82169050919050565b61496a81614939565b82525050565b60006040820190506149856000830185614961565b61499260208301846141c1565b9392505050565b600080600080608085870312156149b3576149b261343f565b5b60006149c1878288016136b9565b94505060206149d287828801613f78565b93505060406149e3878288016136b9565b92505060606149f4878288016136b9565b91505092959194509250565b604082016000820151614a1660008501826138f1565b506020820151614a296020850182613bf1565b50505050565b6000604082019050614a446000830184614a00565b92915050565b614a53816141d0565b8114614a5e57600080fd5b50565b600081359050614a7081614a4a565b92915050565b600060208284031215614a8c57614a8b61343f565b5b6000614a9a84828501614a61565b91505092915050565b600081905092915050565b6000614ab9826139a5565b614ac38185614aa3565b9350614ad38185602086016139c1565b80840191505092915050565b6000614aeb8285614aae565b9150614af78284614aae565b91508190509392505050565b7f436861696e000000000000000000000000000000000000000000000000000000815250565b6000602082019050614b3d60008301614b03565b919050565b600081519050614b5181614a4a565b92915050565b600060208284031215614b6d57614b6c61343f565b5b6000614b7b84828501614b42565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008160e01b9050919050565b6000614bcb82614bb3565b9050919050565b614be3614bde82613be1565b614bc0565b82525050565b6000819050919050565b614c04614bff82613607565b614be9565b82525050565b6000614c168285614bd2565b600482019150614c268284614bf3565b6020820191508190509392505050565b6000819050919050565b614c51614c4c8261363b565b614c36565b82525050565b6000614c638286614aae565b9150614c6f8285614bf3565b602082019150614c7f8284614c40565b602082019150819050949350505050565b600081519050614c9f81613645565b92915050565b600060208284031215614cbb57614cba61343f565b5b6000614cc984828501614c90565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614d0c8261363b565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614d3e57614d3d614cd2565b5b600182019050919050565b6000614d64614d5f614d5a84613be1565b613cda565b61363b565b9050919050565b614d7481614d49565b82525050565b6000606082019050614d8f6000830186614d6b565b614d9c6020830185613d9a565b614da96040830184613d9a565b949350505050565b600067ffffffffffffffff821115614dcc57614dcb613464565b5b614dd582613453565b9050602081019050919050565b6000614df5614df084614db1565b6134c4565b905082815260208101848484011115614e1157614e1061344e565b5b614e1c8482856139c1565b509392505050565b600082601f830112614e3957614e38613449565b5b8151614e49848260208601614de2565b91505092915050565b60008060408385031215614e6957614e6861343f565b5b6000614e7785828601614b42565b925050602083015167ffffffffffffffff811115614e9857614e97613444565b5b614ea485828601614e24565b9150509250929050565b600082825260208201905092915050565b7f5f726567697374727920697320656d7074790000000000000000000000000000600082015250565b6000614ef5601283614eae565b9150614f0082614ebf565b602082019050919050565b60006020820190508181036000830152614f2481614ee8565b9050919050565b7f554d420000000000000000000000000000000000000000000000000000000000815250565b6000602082019050614f6560008301614f2b565b919050565b7f5374616b696e6742616e6b000000000000000000000000000000000000000000815250565b6000602082019050614fa460008301614f6a565b919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000614fdf602083614eae565b9150614fea82614fa9565b602082019050919050565b6000602082019050818103600083015261500e81614fd2565b9050919050565b600061502082613be1565b915061502b83613be1565b92508282101561503e5761503d614cd2565b5b828203905092915050565b60006150548261363b565b915061505f8361363b565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561509457615093614cd2565b5b828201905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006150da8285614aae565b91506150e68284614bf3565b6020820191508190509392505050565b6150ff81613f54565b82525050565b600060808201905061511a6000830187613611565b61512760208301866150f6565b6151346040830185613611565b6151416060830184613611565b95945050505050565b61515381613820565b811461515e57600080fd5b50565b6000815190506151708161514a565b92915050565b60006020828403121561518c5761518b61343f565b5b600061519a84828501615161565b91505092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006151ff602683614eae565b915061520a826151a3565b604082019050919050565b6000602082019050818103600083015261522e816151f2565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61526a81615235565b82525050565b60006020820190506152856000830184615261565b92915050565b60006152978284614aae565b915081905092915050565b6000815190506152b181613e39565b92915050565b6000602082840312156152cd576152cc61343f565b5b60006152db848285016152a2565b91505092915050565b60006152ef82613be1565b91506152fa83613be1565b92508263ffffffff0382111561531357615312614cd2565b5b828201905092915050565b600080fd5b600060a082840312156153395761533861531e565b5b61534360a06134c4565b90506000615353848285016152a2565b6000830152506020615367848285016152a2565b602083015250604061537b848285016152a2565b604083015250606061538f848285016152a2565b60608301525060806153a384828501615161565b60808301525092915050565b600060a082840312156153c5576153c461343f565b5b60006153d384828501615323565b91505092915050565b60006153e782614939565b91506153f283614939565b92508282101561540557615404614cd2565b5b828203905092915050565b600061541b82614939565b915061542683614939565b9250826154365761543561509f565b5b82820490509291505056fea26469706673582212203b81b49a36eda6df7e65aadbd98f4c4b7adc76975d4d22afe7d3b46145920afd64736f6c634300080d0033", "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101f95760003560e01c80630f2acc3e146101fe5780630fcc0c281461022e57806317d7de7c14610238578063199dadc5146102565780631aa3a00814610286578063243b68f91461029057806324c89a49146102c057806326f3ab8b146102de57806334ba34811461030f5780633bb8819d1461032d57806340a9e5e31461035e578063485e055d1461037a5780634bc935d7146103965780634e69d560146103c657806355a373d6146103ee578063637180a81461040c5780636d046c3e1461042a578063715018a6146104485780637353cbcb1461045257806377839fe614610470578063805d34321461048e5780638d068043146104be5780638da5cb5b146104dc5780639f6119d7146104fa578063a0bc937414610518578063abf410e514610536578063adf1639d14610554578063bef9f8a114610585578063bf66e3ba146105b5578063c2a4250b146105e5578063c2b40ae414610603578063c3369db814610633578063ca4d29d214610663578063cbb1b2c714610693578063d3d3ea08146106c4578063d45167d0146106e2578063e76c0b5714610712578063e79a198f14610730578063ed9975c31461073a578063ef19f3e714610758578063f25b3f9914610788578063f2fde38b146107b8578063ffa1ad74146107d4575b600080fd5b6102186004803603810190610213919061358f565b6107f2565b6040516102259190613620565b60405180910390f35b610236610825565b005b610240610997565b60405161024d9190613620565b60405180910390f35b610270600480360381019061026b9190613765565b6109bf565b60405161027d919061383b565b60405180910390f35b61028e610a1b565b005b6102aa60048036038101906102a59190613856565b610c29565b6040516102b79190613983565b60405180910390f35b6102c8610cd2565b6040516102d59190613a2d565b60405180910390f35b6102f860048036038101906102f39190613aaa565b610d0b565b604051610306929190613c83565b60405180910390f35b610317610eaa565b6040516103249190613d39565b60405180910390f35b61034760048036038101906103429190613d54565b610ece565b604051610355929190613da9565b60405180910390f35b61037860048036038101906103739190613e0c565b610f63565b005b610394600480360381019061038f9190614024565b610f73565b005b6103b060048036038101906103ab9190614152565b611546565b6040516103bd919061383b565b60405180910390f35b6103ce61157a565b6040516103e59b9a999897969594939291906143d5565b60405180910390f35b6103f6611b90565b60405161040391906144b6565b60405180910390f35b610414611cbd565b6040516104219190613d39565b60405180910390f35b610432611d5c565b60405161043f919061383b565b60405180910390f35b610450611d61565b005b61045a611de9565b60405161046791906144d1565b60405180910390f35b610478611e2c565b60405161048591906144ec565b60405180910390f35b6104a860048036038101906104a39190614507565b611e49565b6040516104b591906144ec565b60405180910390f35b6104c6611f3d565b6040516104d39190614534565b60405180910390f35b6104e4611f65565b6040516104f1919061454f565b60405180910390f35b610502611f8e565b60405161050f919061454f565b60405180910390f35b610520611faa565b60405161052d91906145e1565b60405180910390f35b61053e612077565b60405161054b919061461d565b60405180910390f35b61056e60048036038101906105699190613d54565b61209b565b60405161057c929190614638565b60405180910390f35b61059f600480360381019061059a9190614661565b612128565b6040516105ac9190613620565b60405180910390f35b6105cf60048036038101906105ca9190614751565b61214b565b6040516105dc91906148d7565b60405180910390f35b6105ed612287565b6040516105fa91906144d1565b60405180910390f35b61061d60048036038101906106189190614507565b6122aa565b60405161062a9190613620565b60405180910390f35b61064d60048036038101906106489190614661565b6122c2565b60405161065a91906144ec565b60405180910390f35b61067d600480360381019061067891906148f9565b6122f7565b60405161068a91906144d1565b60405180910390f35b6106ad60048036038101906106a89190613d54565b612411565b6040516106bb929190614970565b60405180910390f35b6106cc61246d565b6040516106d991906144ec565b60405180910390f35b6106fc60048036038101906106f79190614999565b61248a565b604051610709919061454f565b60405180910390f35b61071a612547565b60405161072791906144ec565b60405180910390f35b610738612583565b005b610742612904565b60405161074f919061454f565b60405180910390f35b610772600480360381019061076d9190614507565b612914565b60405161077f919061454f565b60405180910390f35b6107a2600480360381019061079d9190614507565b612a6c565b6040516107af9190614a2f565b60405180910390f35b6107d260048036038101906107cd9190614a76565b612aa9565b005b6107dc612ba0565b6040516107e991906144d1565b60405180910390f35b60008282604051602001610807929190614adf565b60405160208183030381529060405280519060200120905092915050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156108b45750610884611f65565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156108eb576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160000160109054906101000a900460ff1615610935576040517f764c143b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018060000160106101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167fd4ae81319f0b4df100dcda9ce971671b97278c7a5ce6b37a8331a44700679fd460405160405180910390a2565b60007f436861696e000000000000000000000000000000000000000000000000000000905090565b6000610a11600260008781526020019081526020016000205484846040516020016109eb929190614adf565b6040516020818303038152906040528051906020012086612ba59092919063ffffffff16565b9050949350505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015610aaa5750610a7a611f65565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15610ae1576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b8152600401610b3a90614b29565b602060405180830381865afa158015610b57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7b9190614b57565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610be2576040517f3a81d6fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610c1c5750610c27565b610c2581612bbc565b505b565b606060008267ffffffffffffffff811115610c4757610c46613464565b5b604051908082528060200260200182016040528015610c755781602001602082028036833780820191505090505b50905060005b83811015610cc657600080602087600185010102905080880151915081848481518110610cab57610caa614b84565b5b60200260200101818152505050508080600101915050610c7b565b50809150509392505050565b6040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525081565b6060808383905067ffffffffffffffff811115610d2b57610d2a613464565b5b604051908082528060200260200182016040528015610d595781602001602082028036833780820191505090505b5090508383905067ffffffffffffffff811115610d7957610d78613464565b5b604051908082528060200260200182016040528015610da75781602001602082028036833780820191505090505b50915060005b84849050811015610ea257600060036000878785818110610dd157610dd0614b84565b5b90506020020135815260200190815260200160002090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16848381518110610e4657610e45614b84565b5b60200260200101818152505080600001601c9054906101000a900463ffffffff16838381518110610e7a57610e79614b84565b5b602002602001019063ffffffff16908163ffffffff1681525050818060010192505050610dad565b509250929050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806000600360008581526020019081526020016000209050610f3b8160000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16612efe565b81600001601c9054906101000a900463ffffffff168063ffffffff1690509250925050915091565b610f708161ffff16612fa6565b50565b610f828763ffffffff166130f1565b60008787604051602001610f97929190614c0a565b604051602081830303815290604052905060005b86518110156111a757858181518110610fc757610fc6614b84565b5b6020026020010151868281518110610fe257610fe1614b84565b5b60200260200101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff161461103f576040517f6980091000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604051806040016040528087838151811061105d5761105c614b84565b5b60200260200101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681526020018a63ffffffff16815250600360008984815181106110a9576110a8614b84565b5b6020026020010151815260200190815260200160002060008201518160000160006101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff160217905550602082015181600001601c6101000a81548163ffffffff021916908363ffffffff1602179055509050508187828151811061115457611153614b84565b5b602002602001015187838151811061116f5761116e614b84565b5b602002602001015160405160200161118993929190614c57565b60405160208183030381529060405291508080600101915050610fab565b506000806000838051906020012090506000805b88518110156113b7576000611220848b84815181106111dd576111dc614b84565b5b60200260200101518b85815181106111f8576111f7614b84565b5b60200260200101518b868151811061121357611212614b84565b5b602002602001015161248a565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231836040518263ffffffff1660e01b815260040161127d919061454f565b602060405180830381865afa15801561129a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112be9190614ca5565b90508173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1610611325576040517f9079f69b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8193506000810361133f57828060010193505050506113b2565b868061134a90614d01565b9750508173ffffffffffffffffffffffffffffffffffffffff168f63ffffffff167fbac7552ab5da8d0588709ddb75aceec28520646f54bca1cc5e6e104db61935ec8360405161139a91906144d1565b60405180910390a38086019550828060010193505050505b6111bb565b507f000000000000000000000000000000000000000000000000000000000000000061ffff16841015611416576040517fe246dc6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167f5f11830295067c4bcc7d02d4e3b048cd7427be50a3aeb6afc9d3d559ee64bcfa8d7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114de9190614ca5565b866040516114ee93929190614d7a565b60405180910390a28a600260008e63ffffffff168152602001908152602001600020819055508b600160000160086101000a81548163ffffffff021916908363ffffffff160217905550505050505050505050505050565b60008060001b830361155b5760009050611573565b611570838386612ba59092919063ffffffff16565b90505b9392505050565b6000806000806000806060806060600080600060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff1615151515815250509050439b5080606001519a50806040015198508899507f000000000000000000000000000000000000000000000000000000000000000091507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117159190614ca5565b925060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16639031d9136040518163ffffffff1660e01b8152600401602060405180830381865afa158015611784573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a89190614ca5565b90508067ffffffffffffffff8111156117c4576117c3613464565b5b6040519080825280602002602001820160405280156117f25781602001602082028036833780820191505090505b5095508067ffffffffffffffff81111561180f5761180e613464565b5b60405190808252806020026020018201604052801561183d5781602001602082028036833780820191505090505b5096508067ffffffffffffffff81111561185a57611859613464565b5b60405190808252806020026020018201604052801561188d57816020015b60608152602001906001900390816118785790505b50945060005b81811015611b3b577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663edf26d9b826040518263ffffffff1660e01b81526004016118f491906144d1565b602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119359190614b57565b88828151811061194857611947614b84565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663fa52c7d88983815181106119d1576119d0614b84565b5b60200260200101516040518263ffffffff1660e01b81526004016119f5919061454f565b600060405180830381865afa158015611a12573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611a3b9190614e52565b9050868281518110611a5057611a4f614b84565b5b60200260200101819052507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231898381518110611aaa57611aa9614b84565b5b60200260200101516040518263ffffffff1660e01b8152600401611ace919061454f565b602060405180830381865afa158015611aeb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0f9190614ca5565b878281518110611b2257611b21614b84565b5b6020026020010181815250508080600101915050611893565b50600182606001518b0101975060008111611b57576000611b7f565b86611b6582600142016122f7565b81518110611b7657611b75614b84565b5b60200260200101515b98505050909192939495969798999a565b60008073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1603611c20576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c1790614f0b565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b8152600401611c7790614f51565b602060405180830381865afa158015611c94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cb89190614b57565b905090565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b8152600401611d1690614f90565b602060405180830381865afa158015611d33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d579190614b57565b905090565b600090565b611d69613271565b73ffffffffffffffffffffffffffffffffffffffff16611d87611f65565b73ffffffffffffffffffffffffffffffffffffffff1614611ddd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dd490614ff5565b60405180910390fd5b611de76000613279565b565b6000600160000160009054906101000a900463ffffffff16600160000160049054906101000a900463ffffffff16611e219190615015565b63ffffffff16905090565b6000600160000160009054906101000a900463ffffffff16905090565b60008060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff161515151581525050905082816060015182604001510163ffffffff161015611f2f5782915050611f38565b80604001519150505b919050565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000611fa5600142611fa09190615049565b612914565b905090565b611fb26133c9565b60016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff161515151581525050905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060006003600085815260200190815260200160002090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681600001601c9054906101000a900463ffffffff168063ffffffff1690509250925050915091565b6000600260008363ffffffff168152602001908152602001600020549050919050565b6060815167ffffffffffffffff81111561216857612167613464565b5b6040519080825280602002602001820160405280156121965781602001602082028036833780820191505090505b5090506000805b835181101561227d5761222c600260008984815181106121c0576121bf614b84565b5b602002602001015163ffffffff168152602001908152602001600020548583815181106121f0576121ef614b84565b5b602002602001015161221d89868a87815181106122105761220f614b84565b5b6020026020010151610c29565b612ba59092919063ffffffff16565b83828151811061223f5761223e614b84565b5b60200260200101901515908115158152505084818151811061226457612263614b84565b5b602002602001015182019150808060010191505061219d565b5050949350505050565b6000600160000160089054906101000a900463ffffffff1663ffffffff16905090565b60026020528060005260406000206000915090505481565b60008060001b600260008463ffffffff16815260200190815260200160002054146122ed57816122f0565b60005b9050919050565b60008060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff16151515158152505090506000600182606001510163ffffffff16826040015163ffffffff168503816123e7576123e661509f565b5b04826020015163ffffffff160190508481816124065761240561509f565b5b069250505092915050565b60036020528060005260406000206000915090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169080600001601c9054906101000a900463ffffffff16905082565b6000600160000160089054906101000a900463ffffffff16905090565b6000806040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250866040516020016124d59291906150ce565b604051602081830303815290604052805190602001209050600181868686604051600081526020016040526040516125109493929190615105565b6020604051602081039080840390855afa158015612532573d6000803e3d6000fd5b50505060206040510351915050949350505050565b600080600160000160089054906101000a900463ffffffff1663ffffffff16036125745760009050612580565b61257d42611e49565b90505b90565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415801561261257506125e2611f65565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15612649576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160000160109054906101000a900460ff166129025760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b81526004016126b990614b29565b602060405180830381865afa1580156126d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fa9190614b57565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612761576040517ff8e0084400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006128a0573073ffffffffffffffffffffffffffffffffffffffff16636d046c3e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f59190615176565b15158173ffffffffffffffffffffffffffffffffffffffff16636d046c3e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612842573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128669190615176565b15151461289f576040517f07b72f5e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b60018060000160106101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167fd4ae81319f0b4df100dcda9ce971671b97278c7a5ce6b37a8331a44700679fd460405160405180910390a2505b565b600061290f42612914565b905090565b6000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16639031d9136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612982573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129a69190614ca5565b9050600081036129ba576000915050612a67565b60006129c682856122f7565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663edf26d9b826040518263ffffffff1660e01b8152600401612a2191906144d1565b602060405180830381865afa158015612a3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a629190614b57565b925050505b919050565b612a74613412565b6040518060400160405280600260008581526020019081526020016000205481526020018363ffffffff168152509050919050565b612ab1613271565b73ffffffffffffffffffffffffffffffffffffffff16612acf611f65565b73ffffffffffffffffffffffffffffffffffffffff1614612b25576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b1c90614ff5565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612b94576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b8b90615215565b60405180910390fd5b612b9d81613279565b50565b600281565b600082612bb2858461333d565b1490509392505050565b6000808273ffffffffffffffffffffffffffffffffffffffff167fffa1ad74ba96b4c159a84d090433911c3991c54f629eb60d0c84aed3be5f067c604051602001612c079190615270565b604051602081830303815290604052604051612c23919061528b565b600060405180830381855afa9150503d8060008114612c5e576040519150601f19603f3d011682016040523d82523d6000602084013e612c63565b606091505b5091509150600082612c76576001612c8b565b81806020019051810190612c8a9190614ca5565b5b905060018103612e0b5760008473ffffffffffffffffffffffffffffffffffffffff1663d3d3ea086040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ce2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d0691906152b7565b90508473ffffffffffffffffffffffffffffffffffffffff1663c3369db8826040518263ffffffff1660e01b8152600401612d4191906144ec565b602060405180830381865afa158015612d5e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d8291906152b7565b600160000160086101000a81548163ffffffff021916908363ffffffff160217905550600281612db291906152e4565b600160000160046101000a81548163ffffffff021916908363ffffffff160217905550600281612de291906152e4565b600160000160006101000a81548163ffffffff021916908363ffffffff16021790555050612ef8565b60008473ffffffffffffffffffffffffffffffffffffffff1663a0bc93746040518163ffffffff1660e01b815260040160a060405180830381865afa158015612e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e7c91906153af565b90508060200151600160000160046101000a81548163ffffffff021916908363ffffffff1602179055508060200151600160000160006101000a81548163ffffffff021916908363ffffffff1602179055508060400151600160000160086101000a81548163ffffffff021916908363ffffffff160217905550505b50505050565b60008060007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90506002600182612f3191906153dc565b612f3b9190615410565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1611612f905760008401915081601b0b92505050612fa1565b600181850303915081601b0b925050505b919050565b612fae613271565b73ffffffffffffffffffffffffffffffffffffffff16612fcc611f65565b73ffffffffffffffffffffffffffffffffffffffff1614613022576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161301990614ff5565b60405180910390fd5b8063ffffffff166001600001600c9054906101000a900463ffffffff1663ffffffff160361307c576040517f96f56f6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600001600c6101000a81548163ffffffff021916908363ffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167f02ff77a0f68d11f7efb906f331b2dda82916de8ba9c37dda2a95817936a530ec826040516130e691906144ec565b60405180910390a250565b600060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff16151515158152505090506000816040015163ffffffff16036131f9576040517f96a96e1700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81816060015182604001510163ffffffff1610613242576040517ff886149e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001816020015101600160000160046101000a81548163ffffffff021916908363ffffffff1602179055505050565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60008082905060005b84518110156133a757600085828151811061336457613363614b84565b5b602002602001015190508083116133865761337f83826133b2565b9250613393565b61339081846133b2565b92505b50808061339f90614d01565b915050613346565b508091505092915050565b600082600052816020526040600020905092915050565b6040518060a00160405280600063ffffffff168152602001600063ffffffff168152602001600063ffffffff168152602001600063ffffffff1681526020016000151581525090565b604051806040016040528060008019168152602001600063ffffffff1681525090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61349c82613453565b810181811067ffffffffffffffff821117156134bb576134ba613464565b5b80604052505050565b60006134ce613435565b90506134da8282613493565b919050565b600067ffffffffffffffff8211156134fa576134f9613464565b5b61350382613453565b9050602081019050919050565b82818337600083830152505050565b600061353261352d846134df565b6134c4565b90508281526020810184848401111561354e5761354d61344e565b5b613559848285613510565b509392505050565b600082601f83011261357657613575613449565b5b813561358684826020860161351f565b91505092915050565b600080604083850312156135a6576135a561343f565b5b600083013567ffffffffffffffff8111156135c4576135c3613444565b5b6135d085828601613561565b925050602083013567ffffffffffffffff8111156135f1576135f0613444565b5b6135fd85828601613561565b9150509250929050565b6000819050919050565b61361a81613607565b82525050565b60006020820190506136356000830184613611565b92915050565b6000819050919050565b61364e8161363b565b811461365957600080fd5b50565b60008135905061366b81613645565b92915050565b600067ffffffffffffffff82111561368c5761368b613464565b5b602082029050602081019050919050565b600080fd5b6136ab81613607565b81146136b657600080fd5b50565b6000813590506136c8816136a2565b92915050565b60006136e16136dc84613671565b6134c4565b905080838252602082019050602084028301858111156137045761370361369d565b5b835b8181101561372d578061371988826136b9565b845260208401935050602081019050613706565b5050509392505050565b600082601f83011261374c5761374b613449565b5b813561375c8482602086016136ce565b91505092915050565b6000806000806080858703121561377f5761377e61343f565b5b600061378d8782880161365c565b945050602085013567ffffffffffffffff8111156137ae576137ad613444565b5b6137ba87828801613737565b935050604085013567ffffffffffffffff8111156137db576137da613444565b5b6137e787828801613561565b925050606085013567ffffffffffffffff81111561380857613807613444565b5b61381487828801613561565b91505092959194509250565b60008115159050919050565b61383581613820565b82525050565b6000602082019050613850600083018461382c565b92915050565b60008060006060848603121561386f5761386e61343f565b5b600084013567ffffffffffffffff81111561388d5761388c613444565b5b61389986828701613561565b93505060206138aa8682870161365c565b92505060406138bb8682870161365c565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6138fa81613607565b82525050565b600061390c83836138f1565b60208301905092915050565b6000602082019050919050565b6000613930826138c5565b61393a81856138d0565b9350613945836138e1565b8060005b8381101561397657815161395d8882613900565b975061396883613918565b925050600181019050613949565b5085935050505092915050565b6000602082019050818103600083015261399d8184613925565b905092915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156139df5780820151818401526020810190506139c4565b838111156139ee576000848401525b50505050565b60006139ff826139a5565b613a0981856139b0565b9350613a198185602086016139c1565b613a2281613453565b840191505092915050565b60006020820190508181036000830152613a4781846139f4565b905092915050565b600080fd5b60008083601f840112613a6a57613a69613449565b5b8235905067ffffffffffffffff811115613a8757613a86613a4f565b5b602083019150836020820283011115613aa357613aa261369d565b5b9250929050565b60008060208385031215613ac157613ac061343f565b5b600083013567ffffffffffffffff811115613adf57613ade613444565b5b613aeb85828601613a54565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b613b2c8161363b565b82525050565b6000613b3e8383613b23565b60208301905092915050565b6000602082019050919050565b6000613b6282613af7565b613b6c8185613b02565b9350613b7783613b13565b8060005b83811015613ba8578151613b8f8882613b32565b9750613b9a83613b4a565b925050600181019050613b7b565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600063ffffffff82169050919050565b613bfa81613be1565b82525050565b6000613c0c8383613bf1565b60208301905092915050565b6000602082019050919050565b6000613c3082613bb5565b613c3a8185613bc0565b9350613c4583613bd1565b8060005b83811015613c76578151613c5d8882613c00565b9750613c6883613c18565b925050600181019050613c49565b5085935050505092915050565b60006040820190508181036000830152613c9d8185613b57565b90508181036020830152613cb18184613c25565b90509392505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000613cff613cfa613cf584613cba565b613cda565b613cba565b9050919050565b6000613d1182613ce4565b9050919050565b6000613d2382613d06565b9050919050565b613d3381613d18565b82525050565b6000602082019050613d4e6000830184613d2a565b92915050565b600060208284031215613d6a57613d6961343f565b5b6000613d78848285016136b9565b91505092915050565b6000819050919050565b613d9481613d81565b82525050565b613da38161363b565b82525050565b6000604082019050613dbe6000830185613d8b565b613dcb6020830184613d9a565b9392505050565b600061ffff82169050919050565b613de981613dd2565b8114613df457600080fd5b50565b600081359050613e0681613de0565b92915050565b600060208284031215613e2257613e2161343f565b5b6000613e3084828501613df7565b91505092915050565b613e4281613be1565b8114613e4d57600080fd5b50565b600081359050613e5f81613e39565b92915050565b600067ffffffffffffffff821115613e8057613e7f613464565b5b602082029050602081019050919050565b6000613ea4613e9f84613e65565b6134c4565b90508083825260208201905060208402830185811115613ec757613ec661369d565b5b835b81811015613ef05780613edc888261365c565b845260208401935050602081019050613ec9565b5050509392505050565b600082601f830112613f0f57613f0e613449565b5b8135613f1f848260208601613e91565b91505092915050565b600067ffffffffffffffff821115613f4357613f42613464565b5b602082029050602081019050919050565b600060ff82169050919050565b613f6a81613f54565b8114613f7557600080fd5b50565b600081359050613f8781613f61565b92915050565b6000613fa0613f9b84613f28565b6134c4565b90508083825260208201905060208402830185811115613fc357613fc261369d565b5b835b81811015613fec5780613fd88882613f78565b845260208401935050602081019050613fc5565b5050509392505050565b600082601f83011261400b5761400a613449565b5b813561401b848260208601613f8d565b91505092915050565b600080600080600080600060e0888a0312156140435761404261343f565b5b60006140518a828b01613e50565b97505060206140628a828b016136b9565b965050604088013567ffffffffffffffff81111561408357614082613444565b5b61408f8a828b01613737565b955050606088013567ffffffffffffffff8111156140b0576140af613444565b5b6140bc8a828b01613efa565b945050608088013567ffffffffffffffff8111156140dd576140dc613444565b5b6140e98a828b01613ff6565b93505060a088013567ffffffffffffffff81111561410a57614109613444565b5b6141168a828b01613737565b92505060c088013567ffffffffffffffff81111561413757614136613444565b5b6141438a828b01613737565b91505092959891949750929550565b60008060006060848603121561416b5761416a61343f565b5b600084013567ffffffffffffffff81111561418957614188613444565b5b61419586828701613737565b93505060206141a6868287016136b9565b92505060406141b7868287016136b9565b9150509250925092565b6141ca81613be1565b82525050565b60006141db82613cba565b9050919050565b6141eb816141d0565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b614226816141d0565b82525050565b6000614238838361421d565b60208301905092915050565b6000602082019050919050565b600061425c826141f1565b61426681856141fc565b93506142718361420d565b8060005b838110156142a2578151614289888261422c565b975061429483614244565b925050600181019050614275565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b6000614302826142db565b61430c81856142e6565b935061431c8185602086016139c1565b61432581613453565b840191505092915050565b600061433c83836142f7565b905092915050565b6000602082019050919050565b600061435c826142af565b61436681856142ba565b935083602082028501614378856142cb565b8060005b858110156143b457848403895281516143958582614330565b94506143a083614344565b925060208a0199505060018101905061437c565b50829750879550505050505092915050565b6143cf81613dd2565b82525050565b6000610160820190506143eb600083018e613d9a565b6143f8602083018d6141c1565b614405604083018c6141c1565b614412606083018b6141c1565b61441f608083018a6141e2565b61442c60a08301896141c1565b81810360c083015261443e8188614251565b905081810360e08301526144528187613b57565b90508181036101008301526144678186614351565b9050614477610120830185613d9a565b6144856101408301846143c6565b9c9b505050505050505050505050565b60006144a082613d06565b9050919050565b6144b081614495565b82525050565b60006020820190506144cb60008301846144a7565b92915050565b60006020820190506144e66000830184613d9a565b92915050565b600060208201905061450160008301846141c1565b92915050565b60006020828403121561451d5761451c61343f565b5b600061452b8482850161365c565b91505092915050565b600060208201905061454960008301846143c6565b92915050565b600060208201905061456460008301846141e2565b92915050565b61457381613820565b82525050565b60a08201600082015161458f6000850182613bf1565b5060208201516145a26020850182613bf1565b5060408201516145b56040850182613bf1565b5060608201516145c86060850182613bf1565b5060808201516145db608085018261456a565b50505050565b600060a0820190506145f66000830184614579565b92915050565b600061460782613d06565b9050919050565b614617816145fc565b82525050565b6000602082019050614632600083018461460e565b92915050565b600060408201905061464d6000830185613d9a565b61465a6020830184613d9a565b9392505050565b6000602082840312156146775761467661343f565b5b600061468584828501613e50565b91505092915050565b600067ffffffffffffffff8211156146a9576146a8613464565b5b602082029050602081019050919050565b60006146cd6146c88461468e565b6134c4565b905080838252602082019050602084028301858111156146f0576146ef61369d565b5b835b8181101561471957806147058882613e50565b8452602084019350506020810190506146f2565b5050509392505050565b600082601f83011261473857614737613449565b5b81356147488482602086016146ba565b91505092915050565b6000806000806080858703121561476b5761476a61343f565b5b600085013567ffffffffffffffff81111561478957614788613444565b5b61479587828801614723565b945050602085013567ffffffffffffffff8111156147b6576147b5613444565b5b6147c287828801613561565b935050604085013567ffffffffffffffff8111156147e3576147e2613444565b5b6147ef87828801613efa565b925050606085013567ffffffffffffffff8111156148105761480f613444565b5b61481c87828801613737565b91505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000614860838361456a565b60208301905092915050565b6000602082019050919050565b600061488482614828565b61488e8185614833565b935061489983614844565b8060005b838110156148ca5781516148b18882614854565b97506148bc8361486c565b92505060018101905061489d565b5085935050505092915050565b600060208201905081810360008301526148f18184614879565b905092915050565b600080604083850312156149105761490f61343f565b5b600061491e8582860161365c565b925050602061492f8582860161365c565b9150509250929050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff82169050919050565b61496a81614939565b82525050565b60006040820190506149856000830185614961565b61499260208301846141c1565b9392505050565b600080600080608085870312156149b3576149b261343f565b5b60006149c1878288016136b9565b94505060206149d287828801613f78565b93505060406149e3878288016136b9565b92505060606149f4878288016136b9565b91505092959194509250565b604082016000820151614a1660008501826138f1565b506020820151614a296020850182613bf1565b50505050565b6000604082019050614a446000830184614a00565b92915050565b614a53816141d0565b8114614a5e57600080fd5b50565b600081359050614a7081614a4a565b92915050565b600060208284031215614a8c57614a8b61343f565b5b6000614a9a84828501614a61565b91505092915050565b600081905092915050565b6000614ab9826139a5565b614ac38185614aa3565b9350614ad38185602086016139c1565b80840191505092915050565b6000614aeb8285614aae565b9150614af78284614aae565b91508190509392505050565b7f436861696e000000000000000000000000000000000000000000000000000000815250565b6000602082019050614b3d60008301614b03565b919050565b600081519050614b5181614a4a565b92915050565b600060208284031215614b6d57614b6c61343f565b5b6000614b7b84828501614b42565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008160e01b9050919050565b6000614bcb82614bb3565b9050919050565b614be3614bde82613be1565b614bc0565b82525050565b6000819050919050565b614c04614bff82613607565b614be9565b82525050565b6000614c168285614bd2565b600482019150614c268284614bf3565b6020820191508190509392505050565b6000819050919050565b614c51614c4c8261363b565b614c36565b82525050565b6000614c638286614aae565b9150614c6f8285614bf3565b602082019150614c7f8284614c40565b602082019150819050949350505050565b600081519050614c9f81613645565b92915050565b600060208284031215614cbb57614cba61343f565b5b6000614cc984828501614c90565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614d0c8261363b565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614d3e57614d3d614cd2565b5b600182019050919050565b6000614d64614d5f614d5a84613be1565b613cda565b61363b565b9050919050565b614d7481614d49565b82525050565b6000606082019050614d8f6000830186614d6b565b614d9c6020830185613d9a565b614da96040830184613d9a565b949350505050565b600067ffffffffffffffff821115614dcc57614dcb613464565b5b614dd582613453565b9050602081019050919050565b6000614df5614df084614db1565b6134c4565b905082815260208101848484011115614e1157614e1061344e565b5b614e1c8482856139c1565b509392505050565b600082601f830112614e3957614e38613449565b5b8151614e49848260208601614de2565b91505092915050565b60008060408385031215614e6957614e6861343f565b5b6000614e7785828601614b42565b925050602083015167ffffffffffffffff811115614e9857614e97613444565b5b614ea485828601614e24565b9150509250929050565b600082825260208201905092915050565b7f5f726567697374727920697320656d7074790000000000000000000000000000600082015250565b6000614ef5601283614eae565b9150614f0082614ebf565b602082019050919050565b60006020820190508181036000830152614f2481614ee8565b9050919050565b7f554d420000000000000000000000000000000000000000000000000000000000815250565b6000602082019050614f6560008301614f2b565b919050565b7f5374616b696e6742616e6b000000000000000000000000000000000000000000815250565b6000602082019050614fa460008301614f6a565b919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000614fdf602083614eae565b9150614fea82614fa9565b602082019050919050565b6000602082019050818103600083015261500e81614fd2565b9050919050565b600061502082613be1565b915061502b83613be1565b92508282101561503e5761503d614cd2565b5b828203905092915050565b60006150548261363b565b915061505f8361363b565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561509457615093614cd2565b5b828201905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006150da8285614aae565b91506150e68284614bf3565b6020820191508190509392505050565b6150ff81613f54565b82525050565b600060808201905061511a6000830187613611565b61512760208301866150f6565b6151346040830185613611565b6151416060830184613611565b95945050505050565b61515381613820565b811461515e57600080fd5b50565b6000815190506151708161514a565b92915050565b60006020828403121561518c5761518b61343f565b5b600061519a84828501615161565b91505092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006151ff602683614eae565b915061520a826151a3565b604082019050919050565b6000602082019050818103600083015261522e816151f2565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61526a81615235565b82525050565b60006020820190506152856000830184615261565b92915050565b60006152978284614aae565b915081905092915050565b6000815190506152b181613e39565b92915050565b6000602082840312156152cd576152cc61343f565b5b60006152db848285016152a2565b91505092915050565b60006152ef82613be1565b91506152fa83613be1565b92508263ffffffff0382111561531357615312614cd2565b5b828201905092915050565b600080fd5b600060a082840312156153395761533861531e565b5b61534360a06134c4565b90506000615353848285016152a2565b6000830152506020615367848285016152a2565b602083015250604061537b848285016152a2565b604083015250606061538f848285016152a2565b60608301525060806153a384828501615161565b60808301525092915050565b600060a082840312156153c5576153c461343f565b5b60006153d384828501615323565b91505092915050565b60006153e782614939565b91506153f283614939565b92508282101561540557615404614cd2565b5b828203905092915050565b600061541b82614939565b915061542683614939565b9250826154365761543561509f565b5b82820490509291505056fea26469706673582212203b81b49a36eda6df7e65aadbd98f4c4b7adc76975d4d22afe7d3b46145920afd64736f6c634300080d0033", diff --git a/deployments/bnb_production/StakingBankStatic.json b/deployments/bnb_production/StakingBankStatic.json index e8ab4a4d..39a66a6d 100644 --- a/deployments/bnb_production/StakingBankStatic.json +++ b/deployments/bnb_production/StakingBankStatic.json @@ -1,5 +1,5 @@ { - "address": "0x2d9D79B3189377449aB2AA4bBD2cd2651e0b85BE", + "address": "0x05a86Cc7e4ab36D7e1250B09C278aA34934be7c5", "abi": [ { "inputs": [ @@ -249,58 +249,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "VALIDATOR_15", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATOR_16", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATOR_17", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATOR_18", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "VALIDATOR_2", @@ -812,30 +760,30 @@ "type": "function" } ], - "transactionHash": "0x9f902f8efec706774e29dd0988856b982a29ab51fb7c7ec6d04996a040ed0f30", + "transactionHash": "0x723fc9168112c657a46cf4f02ccc5a3f099b058774afd4eccf7510eb079a8d78", "receipt": { "to": null, "from": "0xA6e4fFa19B213AbeA258ae72e8e1a209B9E543e7", - "contractAddress": "0x2d9D79B3189377449aB2AA4bBD2cd2651e0b85BE", - "transactionIndex": 14, - "gasUsed": "2643132", + "contractAddress": "0x05a86Cc7e4ab36D7e1250B09C278aA34934be7c5", + "transactionIndex": 13, + "gasUsed": "2301671", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xd2a057360390ff64a0b35a916dfafb41f3541ffcd85190e04fac84402603739e", - "transactionHash": "0x9f902f8efec706774e29dd0988856b982a29ab51fb7c7ec6d04996a040ed0f30", + "blockHash": "0x7a9d58117cabf26ab53140c2fba1f9fd6306bc819747f4e8be05b0e5af2f7773", + "transactionHash": "0x723fc9168112c657a46cf4f02ccc5a3f099b058774afd4eccf7510eb079a8d78", "logs": [], - "blockNumber": 33282127, - "cumulativeGasUsed": "4093708", + "blockNumber": 43568867, + "cumulativeGasUsed": "3608892", "status": 1, "byzantium": true }, "args": [ - 19 + 15 ], - "numDeployments": 3, - "solcInputHash": "4db3e1d3dd51dbe508dc0a6a04352df6", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_validatorsCount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"NotSupported\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"minAmountForStake\",\"type\":\"uint256\"}],\"name\":\"LogMinAmountForStake\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"NUMBER_OF_VALIDATORS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ONE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TOTAL_SUPPLY\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_0\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_1\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_10\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_11\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_12\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_13\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_14\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_15\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_16\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_17\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_18\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_2\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_3\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_4\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_5\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_6\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_7\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_8\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_9\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_ix\",\"type\":\"uint256\"}],\"name\":\"addresses\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validator\",\"type\":\"address\"}],\"name\":\"balances\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"create\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"exit\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBalances\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"allBalances\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumberOfValidators\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"receiveApproval\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"register\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"remove\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"setMinAmountForStake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"stake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"update\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_id\",\"type\":\"address\"}],\"name\":\"validators\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"location\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_validators\",\"type\":\"address[]\"}],\"name\":\"verifyValidators\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addresses(uint256)\":{\"details\":\"gets validator address for provided index\",\"params\":{\"_ix\":\"index in array of list of all validators wallets\"}},\"balanceOf(address)\":{\"details\":\"to follow ERC20 interface\"},\"exit()\":{\"details\":\"unstake and withdraw all tokens\"},\"getName()\":{\"details\":\"to follow Registrable interface\"},\"getNumberOfValidators()\":{\"returns\":{\"_0\":\"total number of registered validators (with and without balance)\"}},\"register()\":{\"details\":\"to follow Registrable interface\"},\"totalSupply()\":{\"details\":\"to follow ERC20 interface\"},\"unregister()\":{\"details\":\"to follow Registrable interface\"},\"validators(address)\":{\"params\":{\"_id\":\"address of validator\"},\"returns\":{\"id\":\"address of validator\",\"location\":\"URL of validator\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":\"StakingBankStaticProd\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":0},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBank.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IStakingBank is IERC20 {\\n /// @param id address of validator wallet\\n /// @param location URL of the validator API\\n struct Validator {\\n address id;\\n string location;\\n }\\n\\n event LogValidatorRegistered(address indexed id);\\n event LogValidatorUpdated(address indexed id);\\n event LogValidatorRemoved(address indexed id);\\n event LogMinAmountForStake(uint256 minAmountForStake);\\n\\n /// @dev setter for `minAmountForStake`\\n function setMinAmountForStake(uint256 _minAmountForStake) external;\\n\\n /// @dev allows to stake `token` by validators\\n /// Validator needs to approve StakingBank beforehand\\n /// @param _value amount of tokens to stake\\n function stake(uint256 _value) external;\\n\\n /// @dev notification about approval from `_from` address on UMB token\\n /// Staking bank will stake max approved amount from `_from` address\\n /// @param _from address which approved token spend for IStakingBank\\n function receiveApproval(address _from) external returns (bool success);\\n\\n /// @dev withdraws stake tokens\\n /// it throws, when balance will be less than required minimum for stake\\n /// to withdraw all use `exit`\\n function withdraw(uint256 _value) external returns (bool success);\\n\\n /// @dev unstake and withdraw all tokens\\n function exit() external returns (bool success);\\n\\n /// @dev creates (register) new validator\\n /// @param _id validator address\\n /// @param _location location URL of the validator API\\n function create(address _id, string calldata _location) external;\\n\\n /// @dev removes validator\\n /// @param _id validator wallet\\n function remove(address _id) external;\\n\\n /// @dev updates validator location\\n /// @param _id validator wallet\\n /// @param _location new validator URL\\n function update(address _id, string calldata _location) external;\\n\\n /// @return total number of registered validators (with and without balance)\\n function getNumberOfValidators() external view returns (uint256);\\n\\n /// @dev gets validator address for provided index\\n /// @param _ix index in array of list of all validators wallets\\n function addresses(uint256 _ix) external view returns (address);\\n\\n /// @param _id address of validator\\n /// @return id address of validator\\n /// @return location URL of validator\\n function validators(address _id) external view returns (address id, string memory location);\\n}\\n\",\"keccak256\":\"0x2c518aeab8b0b3a364fafaec559d3ff0dc6a119f8d203fa31ef7ad667ca0f7b9\",\"license\":\"MIT\"},\"contracts/interfaces/StakingBankStaticNotSupported.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./IStakingBank.sol\\\";\\n\\nabstract contract StakingBankStaticNotSupported is IStakingBank {\\n error NotSupported();\\n\\n function create(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function update(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function remove(address) external pure {\\n revert NotSupported();\\n }\\n\\n function transfer(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function transferFrom(address, address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function receiveApproval(address) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function allowance(address, address) external pure returns (uint256) {\\n revert NotSupported();\\n }\\n\\n function approve(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function stake(uint256) external pure {\\n revert NotSupported();\\n }\\n\\n function withdraw(uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function exit() external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function setMinAmountForStake(uint256) external pure {\\n revert NotSupported();\\n }\\n}\\n\",\"keccak256\":\"0xa899ad9000220b04bc3f63f762a9a6a76dcc09449427e7774a53f4ceda9c1cf8\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStatic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"../interfaces/StakingBankStaticNotSupported.sol\\\";\\n\\n/// @dev Because we are using PoA in UMB oracle, staked balance does not matter. What's matter is, if signer is\\n/// validator or not. In this case we can optimise `StakingBank` and make it static for better gas performance.\\nabstract contract StakingBankStatic is StakingBankStaticNotSupported {\\n uint256 public constant ONE = 1e18;\\n\\n uint256 public immutable NUMBER_OF_VALIDATORS; // solhint-disable-line var-name-mixedcase\\n uint256 public immutable TOTAL_SUPPLY; // solhint-disable-line var-name-mixedcase\\n\\n constructor(uint256 _validatorsCount) {\\n NUMBER_OF_VALIDATORS = _validatorsCount;\\n TOTAL_SUPPLY = _validatorsCount * ONE;\\n\\n _assertValidSetup(_validatorsCount);\\n }\\n\\n function balances(address _validator) external view returns (uint256) {\\n return _isValidator(_validator) ? ONE : 0;\\n }\\n\\n function verifyValidators(address[] calldata _validators) external view returns (bool) {\\n for (uint256 i; i < _validators.length;) {\\n if (!_isValidator(_validators[i])) return false;\\n unchecked { i++; }\\n }\\n\\n return true;\\n }\\n\\n function getNumberOfValidators() external view returns (uint256) {\\n return NUMBER_OF_VALIDATORS;\\n }\\n\\n function getAddresses() external view returns (address[] memory) {\\n return _addresses();\\n }\\n\\n function getBalances() external view returns (uint256[] memory allBalances) {\\n allBalances = new uint256[](NUMBER_OF_VALIDATORS);\\n\\n for (uint256 i; i < NUMBER_OF_VALIDATORS;) {\\n allBalances[i] = ONE;\\n\\n unchecked {\\n // we will not have enough data to overflow\\n i++;\\n }\\n }\\n }\\n\\n function addresses(uint256 _ix) external view returns (address) {\\n return _addresses()[_ix];\\n }\\n\\n function validators(address _id) external view virtual returns (address id, string memory location);\\n\\n /// @dev to follow ERC20 interface\\n function balanceOf(address _account) external view returns (uint256) {\\n return _isValidator(_account) ? ONE : 0;\\n }\\n\\n /// @dev to follow ERC20 interface\\n function totalSupply() external view returns (uint256) {\\n return TOTAL_SUPPLY;\\n }\\n\\n /// @dev to follow Registrable interface\\n function getName() external pure returns (bytes32) {\\n return \\\"StakingBank\\\";\\n }\\n\\n /// @dev to follow Registrable interface\\n function register() external pure {\\n // there are no requirements atm\\n }\\n\\n /// @dev to follow Registrable interface\\n function unregister() external pure {\\n // there are no requirements atm\\n }\\n\\n function _addresses() internal view virtual returns (address[] memory);\\n\\n function _isValidator(address _validator) internal view virtual returns (bool);\\n\\n function _assertValidSetup(uint256 _validatorsCount) internal view virtual{\\n address[] memory list = _addresses();\\n require(list.length == _validatorsCount);\\n\\n for (uint256 i; i < _validatorsCount;) {\\n require(_isValidator(list[i]));\\n\\n unchecked { i ++; }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfcc53ff98b0f1c42e1bc7345a1535fdc4e938ef40d323600ead94b2ece59a381\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./StakingBankStatic.sol\\\";\\n\\ncontract StakingBankStaticProd is StakingBankStatic {\\n address public constant VALIDATOR_0 = 0x977Ba523420110e230643B772Fe9cF955e11dA7B;\\n address public constant VALIDATOR_1 = 0xe2422b23e52bc13ebA04d7FbB9F332Deb43360fB;\\n\\n // external order is based on validators submits on AVAX for Apr 2023\\n address public constant VALIDATOR_2 = 0x57F404aD75e371c1A539589C1eFCA12e0C6980AD;\\n address public constant VALIDATOR_3 = 0xD56C6A4f64E0bD70260472d1DB6Cf5825858CB0d;\\n address public constant VALIDATOR_4 = 0x220230Eda8f50067Dd9e4729345dabCCe0C61542;\\n address public constant VALIDATOR_5 = 0x93FdcAB283b0BcAc48157590af482E1CFd6af6aC;\\n address public constant VALIDATOR_6 = 0xCd733E06B06083d52fC5867E8E3432aA5c103A38;\\n address public constant VALIDATOR_7 = 0x42e210b110c6aa49CdfA7ceF1444Aa4719653111;\\n address public constant VALIDATOR_8 = 0x501731c6a69803a53Ec6c3e12f293c247cE1092B;\\n address public constant VALIDATOR_9 = 0x8bF9661F1b247522C75DD0FE84355aD2EfF27144;\\n address public constant VALIDATOR_10 = 0x281754Ab58391A478B7aA4E7f39991CfB41118c4;\\n address public constant VALIDATOR_11 = 0xB9C63a350A04d8BD245d18928a26EE036352dDd8;\\n address public constant VALIDATOR_12 = 0x57A51D5BDcE188c2295fCA3b4687475a54E65A02;\\n address public constant VALIDATOR_13 = 0x777FbA3666fa7747476a34577FcCC404b263E09F;\\n address public constant VALIDATOR_14 = 0x2F85824B2B38F179E451988670935d315b5b9692;\\n address public constant VALIDATOR_15 = 0xA7241994267682de4dE7Ef62f52dc2C783d1784B;\\n address public constant VALIDATOR_16 = 0x6eEd457C20603EDAE50C3A112CAA1a9425321bD0;\\n address public constant VALIDATOR_17 = 0xC5a7650c2725a7B6A39f15cb9FbffC7af357AFeb;\\n address public constant VALIDATOR_18 = 0xFEd95453678920c1b7b3A81F033Ca02a27225556;\\n\\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\\n\\n // solhint-disable-next-line code-complexity\\n function validators(address _id) external pure override returns (address id, string memory location) {\\n if (_id == VALIDATOR_0) return (_id, \\\"https://validator.umb.network\\\");\\n if (_id == VALIDATOR_1) return (_id, \\\"https://validator2.umb.network\\\");\\n if (_id == VALIDATOR_2) return (_id, \\\"https://umbrella.artemahr.tech\\\");\\n if (_id == VALIDATOR_3) return (_id, \\\"https://umb.vtabsolutions.com:3030\\\");\\n if (_id == VALIDATOR_4) return (_id, \\\"https://umb.stakers.world\\\");\\n if (_id == VALIDATOR_5) return (_id, \\\"https://umbrella.crazywhale.es\\\");\\n if (_id == VALIDATOR_6) return (_id, \\\"https://umbrella-node.gateomega.com\\\");\\n if (_id == VALIDATOR_7) return (_id, \\\"https://umb.anorak.technology\\\");\\n if (_id == VALIDATOR_8) return (_id, \\\"https://umbrella.validator.infstones.io\\\");\\n if (_id == VALIDATOR_9) return (_id, \\\"https://umb.hashquark.io\\\");\\n if (_id == VALIDATOR_10) return (_id, \\\"http://umbrella.staking4all.org:3000\\\");\\n if (_id == VALIDATOR_11) return (_id, \\\"https://umbrella-api.validatrium.club\\\");\\n if (_id == VALIDATOR_12) return (_id, \\\"http://5.161.78.230:3000\\\");\\n if (_id == VALIDATOR_13) return (_id, \\\"https://umbnode.blockchainliverpool.com\\\");\\n if (_id == VALIDATOR_14) return (_id, \\\"https://umb-api.staking.rocks\\\");\\n if (_id == VALIDATOR_15) return (_id, \\\"https://rpc.urbanhq.net\\\");\\n if (_id == VALIDATOR_16) return (_id, \\\"https://umbrella-node.ankastake.com\\\");\\n if (_id == VALIDATOR_17) return (_id, \\\"https://umbrella.tchambrella.com\\\");\\n if (_id == VALIDATOR_18) return (_id, \\\"https://umbrella-node.cmt13.eu\\\");\\n\\n return (address(0), \\\"\\\");\\n }\\n\\n function _addresses() internal view override returns (address[] memory) {\\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\\n\\n list[0] = VALIDATOR_0;\\n list[1] = VALIDATOR_1;\\n list[2] = VALIDATOR_2;\\n list[3] = VALIDATOR_3;\\n list[4] = VALIDATOR_4;\\n list[5] = VALIDATOR_5;\\n list[6] = VALIDATOR_6;\\n list[7] = VALIDATOR_7;\\n list[8] = VALIDATOR_8;\\n list[9] = VALIDATOR_9;\\n list[10] = VALIDATOR_10;\\n list[11] = VALIDATOR_11;\\n list[12] = VALIDATOR_12;\\n list[13] = VALIDATOR_13;\\n list[14] = VALIDATOR_14;\\n list[15] = VALIDATOR_15;\\n list[16] = VALIDATOR_16;\\n list[17] = VALIDATOR_17;\\n list[18] = VALIDATOR_18;\\n\\n return list;\\n }\\n\\n function _isValidator(address _validator) internal pure override returns (bool) {\\n return (\\n _validator == VALIDATOR_0\\n || _validator == VALIDATOR_1\\n || _validator == VALIDATOR_2\\n || _validator == VALIDATOR_3\\n || _validator == VALIDATOR_4\\n || _validator == VALIDATOR_5\\n || _validator == VALIDATOR_6\\n || _validator == VALIDATOR_7\\n || _validator == VALIDATOR_8\\n || _validator == VALIDATOR_9\\n || _validator == VALIDATOR_10\\n || _validator == VALIDATOR_11\\n || _validator == VALIDATOR_12\\n || _validator == VALIDATOR_13\\n || _validator == VALIDATOR_14\\n || _validator == VALIDATOR_15\\n || _validator == VALIDATOR_16\\n || _validator == VALIDATOR_17\\n || _validator == VALIDATOR_18\\n );\\n }\\n}\\n\",\"keccak256\":\"0x1e80a063f381fdb75109238bd1e4db75af37b5aea8d8165293aee4bf84838c85\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60c06040523480156200001157600080fd5b5060405162003da238038062003da2833981810160405281019062000037919062000eaf565b808060808181525050670de0b6b3a76400008162000056919062000f10565b60a081815250506200006e816200007660201b60201c565b505062000fcf565b600062000088620000ef60201b60201c565b9050818151146200009857600080fd5b60005b82811015620000ea57620000d2828281518110620000be57620000bd62000f71565b5b6020026020010151620008dd60201b60201c565b620000dc57600080fd5b80806001019150506200009b565b505050565b6060600060805167ffffffffffffffff81111562000112576200011162000fa0565b5b604051908082528060200260200182016040528015620001415781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b8160008151811062000170576200016f62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110620001d657620001d562000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad816002815181106200023c576200023b62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110620002a257620002a162000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073220230eda8f50067dd9e4729345dabcce0c615428160048151811062000308576200030762000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac816005815181106200036e576200036d62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a3881600681518110620003d457620003d362000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa4719653111816007815181106200043a576200043962000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b81600881518110620004a0576200049f62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff271448160098151811062000506576200050562000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600a815181106200056c576200056b62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073b9c63a350a04d8bd245d18928a26ee036352ddd881600b81518110620005d257620005d162000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600c8151811062000638576200063762000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073777fba3666fa7747476a34577fccc404b263e09f81600d815181106200069e576200069d62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600e8151811062000704576200070362000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600f815181106200076a576200076962000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081601081518110620007d057620007cf62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb8160118151811062000836576200083562000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073fed95453678920c1b7b3a81f033ca02a27225556816012815181106200089c576200089b62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806200096d575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80620009b857507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a03575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a4e575073220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a9957507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ae4575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b2f57507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b7a575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000bc55750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000c10575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000c5b575073b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ca657507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000cf1575073777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000d3c5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000d87575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000dd25750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000e1d575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000e68575073fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b600080fd5b6000819050919050565b62000e898162000e74565b811462000e9557600080fd5b50565b60008151905062000ea98162000e7e565b92915050565b60006020828403121562000ec85762000ec762000e6f565b5b600062000ed88482850162000e98565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600062000f1d8262000e74565b915062000f2a8362000e74565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161562000f665762000f6562000ee1565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60805160a051612d8a62001018600039600081816109ac0152610c2e01526000818161081b0152818161088901528181610c5401528181610dbd0152611db40152612d8a6000f3fe608060405234801561001057600080fd5b50600436106102195760003560e01c8062113e081461021e578063015f7ed61461023c57806303a1e2241461025a578063095ea7b3146102785780630db18e37146102a857806317d7de7c146102d857806318160ddd146102f65780631aa3a008146103145780631d4f9ce01461031e57806323b872dd1461034e57806327e235e31461037e57806329092d0e146103ae5780632e1a7d4d146103ca578063398b056e146103fa578063411ff4971461041857806345f9f8251461043657806352b41e351461045457806354755335146104705780635dc4bfd31461048e57806361a3e37e146104ac57806369dc7ae4146104ca57806370a08231146104e8578063838e7c3a14610518578063902d55a5146105345780639031d9131461055257806390ff7e2e14610570578063952c4f181461058e578063989b6996146105ac5780639f0e9484146105ca578063a15ab08d146105e8578063a39fac1214610604578063a694fc3a14610622578063a9059cbb1461063e578063b2119eac1461066e578063b49b08421461068c578063c2ee3a08146106aa578063db731777146106c8578063dd62ed3e146106e6578063e214a5fc14610716578063e29349d614610734578063e2dc7a1a14610752578063e79a198f14610770578063e985e0081461077a578063e9fad8ee14610798578063edf26d9b146107b6578063fa52c7d8146107e6575b600080fd5b610226610817565b6040516102339190612645565b60405180910390f35b6102446108e8565b60405161025191906126a8565b60405180910390f35b610262610900565b60405161026f91906126a8565b60405180910390f35b610292600480360381019061028d9190612725565b610918565b60405161029f9190612780565b60405180910390f35b6102c260048036038101906102bd919061279b565b61094c565b6040516102cf9190612780565b60405180910390f35b6102e0610980565b6040516102ed91906127e1565b60405180910390f35b6102fe6109a8565b60405161030b919061280b565b60405180910390f35b61031c6109d0565b005b6103386004803603810190610333919061288b565b6109d2565b6040516103459190612780565b60405180910390f35b610368600480360381019061036391906128d8565b610a38565b6040516103759190612780565b60405180910390f35b6103986004803603810190610393919061279b565b610a6c565b6040516103a5919061280b565b60405180910390f35b6103c860048036038101906103c3919061279b565b610a93565b005b6103e460048036038101906103df919061292b565b610ac5565b6040516103f19190612780565b60405180910390f35b610402610af9565b60405161040f91906126a8565b60405180910390f35b610420610b11565b60405161042d91906126a8565b60405180910390f35b61043e610b29565b60405161044b91906126a8565b60405180910390f35b61046e6004803603810190610469919061292b565b610b41565b005b610478610b73565b60405161048591906126a8565b60405180910390f35b610496610b8b565b6040516104a391906126a8565b60405180910390f35b6104b4610ba3565b6040516104c191906126a8565b60405180910390f35b6104d2610bbb565b6040516104df91906126a8565b60405180910390f35b61050260048036038101906104fd919061279b565b610bd3565b60405161050f919061280b565b60405180910390f35b610532600480360381019061052d91906129ae565b610bfa565b005b61053c610c2c565b604051610549919061280b565b60405180910390f35b61055a610c50565b604051610567919061280b565b60405180910390f35b610578610c78565b60405161058591906126a8565b60405180910390f35b610596610c90565b6040516105a391906126a8565b60405180910390f35b6105b4610ca8565b6040516105c191906126a8565b60405180910390f35b6105d2610cc0565b6040516105df91906126a8565b60405180910390f35b61060260048036038101906105fd91906129ae565b610cd8565b005b61060c610d0a565b6040516106199190612acc565b60405180910390f35b61063c6004803603810190610637919061292b565b610d19565b005b61065860048036038101906106539190612725565b610d4b565b6040516106659190612780565b60405180910390f35b610676610d7f565b60405161068391906126a8565b60405180910390f35b610694610d97565b6040516106a191906126a8565b60405180910390f35b6106b2610daf565b6040516106bf919061280b565b60405180910390f35b6106d0610dbb565b6040516106dd919061280b565b60405180910390f35b61070060048036038101906106fb9190612aee565b610ddf565b60405161070d919061280b565b60405180910390f35b61071e610e13565b60405161072b91906126a8565b60405180910390f35b61073c610e2b565b60405161074991906126a8565b60405180910390f35b61075a610e43565b60405161076791906126a8565b60405180910390f35b610778610e5b565b005b610782610e5d565b60405161078f91906126a8565b60405180910390f35b6107a0610e75565b6040516107ad9190612780565b60405180910390f35b6107d060048036038101906107cb919061292b565b610ea9565b6040516107dd91906126a8565b60405180910390f35b61080060048036038101906107fb919061279b565b610ed4565b60405161080e929190612bc7565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff81111561085357610852612bf7565b5b6040519080825280602002602001820160405280156108815781602001602082028036833780820191505090505b50905060005b7f00000000000000000000000000000000000000000000000000000000000000008110156108e457670de0b6b3a76400008282815181106108cb576108ca612c26565b5b6020026020010181815250508080600101915050610887565b5090565b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b83839050811015610a2c57610a118484838181106109f7576109f6612c26565b5b9050602002016020810190610a0c919061279b565b61182e565b610a1f576000915050610a32565b80806001019150506109d6565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a778261182e565b610a82576000610a8c565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b732f85824b2b38f179e451988670935d315b5b969281565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b73fed95453678920c1b7b3a81f033ca02a2722555681565b73777fba3666fa7747476a34577fccc404b263e09f81565b6000610bde8261182e565b610be9576000610bf3565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b73220230eda8f50067dd9e4729345dabcce0c6154281565b73a7241994267682de4de7ef62f52dc2c783d1784b81565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610d14611dae565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73281754ab58391a478b7aa4e7f39991cfb41118c481565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b736eed457c20603edae50c3a112caa1a9425321bd081565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b565b73b9c63a350a04d8bd245d18928a26ee036352ddd881565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610eb3611dae565b8281518110610ec557610ec4612c26565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f5f57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611829565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fe657826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611829565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361106d57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611829565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110d75782604051806060016040528060228152602001612c796022913991509150611829565b73220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361115e57826040518060400160405280601981526020017f68747470733a2f2f756d622e7374616b6572732e776f726c640000000000000081525091509150611829565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111e557826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611829565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361124f5782604051806060016040528060238152602001612c566023913991509150611829565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112d657826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611829565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113405782604051806060016040528060278152602001612cbf6027913991509150611829565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113c757826040518060400160405280601881526020017f68747470733a2f2f756d622e68617368717561726b2e696f000000000000000081525091509150611829565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114315782604051806060016040528060248152602001612c9b6024913991509150611829565b73b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361149b5782604051806060016040528060258152602001612ce66025913991509150611829565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152257826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611829565b73777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361158c5782604051806060016040528060278152602001612d2e6027913991509150611829565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361161357826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611829565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361169a57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611829565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036117045782604051806060016040528060238152602001612d0b6023913991509150611829565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361178b57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611829565b73fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361181257826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612d6e6f64652e636d7431332e6575000081525091509150611829565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806118bd575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061190757507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611951575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061199b575073220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806119e557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a2f575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a7957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ac3575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b0d5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b57575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ba1575073b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611beb57507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c35575073777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c7f5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611cc9575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d135750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d5d575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611da7575073fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff811115611dec57611deb612bf7565b5b604051908082528060200260200182016040528015611e1a5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611e4657611e45612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611ea957611ea8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611f0c57611f0b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611f6f57611f6e612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073220230eda8f50067dd9e4729345dabcce0c6154281600481518110611fd257611fd1612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac8160058151811061203557612034612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a388160068151811061209857612097612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa4719653111816007815181106120fb576120fa612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b8160088151811061215e5761215d612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff27144816009815181106121c1576121c0612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600a8151811061222457612223612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073b9c63a350a04d8bd245d18928a26ee036352ddd881600b8151811061228757612286612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600c815181106122ea576122e9612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073777fba3666fa7747476a34577fccc404b263e09f81600d8151811061234d5761234c612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600e815181106123b0576123af612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600f8151811061241357612412612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd08160108151811061247657612475612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb816011815181106124d9576124d8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073fed95453678920c1b7b3a81f033ca02a272255568160128151811061253c5761253b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6125bc816125a9565b82525050565b60006125ce83836125b3565b60208301905092915050565b6000602082019050919050565b60006125f28261257d565b6125fc8185612588565b935061260783612599565b8060005b8381101561263857815161261f88826125c2565b975061262a836125da565b92505060018101905061260b565b5085935050505092915050565b6000602082019050818103600083015261265f81846125e7565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061269282612667565b9050919050565b6126a281612687565b82525050565b60006020820190506126bd6000830184612699565b92915050565b600080fd5b600080fd5b6126d681612687565b81146126e157600080fd5b50565b6000813590506126f3816126cd565b92915050565b612702816125a9565b811461270d57600080fd5b50565b60008135905061271f816126f9565b92915050565b6000806040838503121561273c5761273b6126c3565b5b600061274a858286016126e4565b925050602061275b85828601612710565b9150509250929050565b60008115159050919050565b61277a81612765565b82525050565b60006020820190506127956000830184612771565b92915050565b6000602082840312156127b1576127b06126c3565b5b60006127bf848285016126e4565b91505092915050565b6000819050919050565b6127db816127c8565b82525050565b60006020820190506127f660008301846127d2565b92915050565b612805816125a9565b82525050565b600060208201905061282060008301846127fc565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261284b5761284a612826565b5b8235905067ffffffffffffffff8111156128685761286761282b565b5b60208301915083602082028301111561288457612883612830565b5b9250929050565b600080602083850312156128a2576128a16126c3565b5b600083013567ffffffffffffffff8111156128c0576128bf6126c8565b5b6128cc85828601612835565b92509250509250929050565b6000806000606084860312156128f1576128f06126c3565b5b60006128ff868287016126e4565b9350506020612910868287016126e4565b925050604061292186828701612710565b9150509250925092565b600060208284031215612941576129406126c3565b5b600061294f84828501612710565b91505092915050565b60008083601f84011261296e5761296d612826565b5b8235905067ffffffffffffffff81111561298b5761298a61282b565b5b6020830191508360018202830111156129a7576129a6612830565b5b9250929050565b6000806000604084860312156129c7576129c66126c3565b5b60006129d5868287016126e4565b935050602084013567ffffffffffffffff8111156129f6576129f56126c8565b5b612a0286828701612958565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b612a4381612687565b82525050565b6000612a558383612a3a565b60208301905092915050565b6000602082019050919050565b6000612a7982612a0e565b612a838185612a19565b9350612a8e83612a2a565b8060005b83811015612abf578151612aa68882612a49565b9750612ab183612a61565b925050600181019050612a92565b5085935050505092915050565b60006020820190508181036000830152612ae68184612a6e565b905092915050565b60008060408385031215612b0557612b046126c3565b5b6000612b13858286016126e4565b9250506020612b24858286016126e4565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612b68578082015181840152602081019050612b4d565b83811115612b77576000848401525b50505050565b6000601f19601f8301169050919050565b6000612b9982612b2e565b612ba38185612b39565b9350612bb3818560208601612b4a565b612bbc81612b7d565b840191505092915050565b6000604082019050612bdc6000830185612699565b8181036020830152612bee8184612b8e565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6170692e76616c696461747269756d2e636c756268747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6d68747470733a2f2f756d626e6f64652e626c6f636b636861696e6c69766572706f6f6c2e636f6da26469706673582212209a1752a9ea487818b8a4d658f151da9487c0cc92638142159bacde7ec2d21f7564736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102195760003560e01c8062113e081461021e578063015f7ed61461023c57806303a1e2241461025a578063095ea7b3146102785780630db18e37146102a857806317d7de7c146102d857806318160ddd146102f65780631aa3a008146103145780631d4f9ce01461031e57806323b872dd1461034e57806327e235e31461037e57806329092d0e146103ae5780632e1a7d4d146103ca578063398b056e146103fa578063411ff4971461041857806345f9f8251461043657806352b41e351461045457806354755335146104705780635dc4bfd31461048e57806361a3e37e146104ac57806369dc7ae4146104ca57806370a08231146104e8578063838e7c3a14610518578063902d55a5146105345780639031d9131461055257806390ff7e2e14610570578063952c4f181461058e578063989b6996146105ac5780639f0e9484146105ca578063a15ab08d146105e8578063a39fac1214610604578063a694fc3a14610622578063a9059cbb1461063e578063b2119eac1461066e578063b49b08421461068c578063c2ee3a08146106aa578063db731777146106c8578063dd62ed3e146106e6578063e214a5fc14610716578063e29349d614610734578063e2dc7a1a14610752578063e79a198f14610770578063e985e0081461077a578063e9fad8ee14610798578063edf26d9b146107b6578063fa52c7d8146107e6575b600080fd5b610226610817565b6040516102339190612645565b60405180910390f35b6102446108e8565b60405161025191906126a8565b60405180910390f35b610262610900565b60405161026f91906126a8565b60405180910390f35b610292600480360381019061028d9190612725565b610918565b60405161029f9190612780565b60405180910390f35b6102c260048036038101906102bd919061279b565b61094c565b6040516102cf9190612780565b60405180910390f35b6102e0610980565b6040516102ed91906127e1565b60405180910390f35b6102fe6109a8565b60405161030b919061280b565b60405180910390f35b61031c6109d0565b005b6103386004803603810190610333919061288b565b6109d2565b6040516103459190612780565b60405180910390f35b610368600480360381019061036391906128d8565b610a38565b6040516103759190612780565b60405180910390f35b6103986004803603810190610393919061279b565b610a6c565b6040516103a5919061280b565b60405180910390f35b6103c860048036038101906103c3919061279b565b610a93565b005b6103e460048036038101906103df919061292b565b610ac5565b6040516103f19190612780565b60405180910390f35b610402610af9565b60405161040f91906126a8565b60405180910390f35b610420610b11565b60405161042d91906126a8565b60405180910390f35b61043e610b29565b60405161044b91906126a8565b60405180910390f35b61046e6004803603810190610469919061292b565b610b41565b005b610478610b73565b60405161048591906126a8565b60405180910390f35b610496610b8b565b6040516104a391906126a8565b60405180910390f35b6104b4610ba3565b6040516104c191906126a8565b60405180910390f35b6104d2610bbb565b6040516104df91906126a8565b60405180910390f35b61050260048036038101906104fd919061279b565b610bd3565b60405161050f919061280b565b60405180910390f35b610532600480360381019061052d91906129ae565b610bfa565b005b61053c610c2c565b604051610549919061280b565b60405180910390f35b61055a610c50565b604051610567919061280b565b60405180910390f35b610578610c78565b60405161058591906126a8565b60405180910390f35b610596610c90565b6040516105a391906126a8565b60405180910390f35b6105b4610ca8565b6040516105c191906126a8565b60405180910390f35b6105d2610cc0565b6040516105df91906126a8565b60405180910390f35b61060260048036038101906105fd91906129ae565b610cd8565b005b61060c610d0a565b6040516106199190612acc565b60405180910390f35b61063c6004803603810190610637919061292b565b610d19565b005b61065860048036038101906106539190612725565b610d4b565b6040516106659190612780565b60405180910390f35b610676610d7f565b60405161068391906126a8565b60405180910390f35b610694610d97565b6040516106a191906126a8565b60405180910390f35b6106b2610daf565b6040516106bf919061280b565b60405180910390f35b6106d0610dbb565b6040516106dd919061280b565b60405180910390f35b61070060048036038101906106fb9190612aee565b610ddf565b60405161070d919061280b565b60405180910390f35b61071e610e13565b60405161072b91906126a8565b60405180910390f35b61073c610e2b565b60405161074991906126a8565b60405180910390f35b61075a610e43565b60405161076791906126a8565b60405180910390f35b610778610e5b565b005b610782610e5d565b60405161078f91906126a8565b60405180910390f35b6107a0610e75565b6040516107ad9190612780565b60405180910390f35b6107d060048036038101906107cb919061292b565b610ea9565b6040516107dd91906126a8565b60405180910390f35b61080060048036038101906107fb919061279b565b610ed4565b60405161080e929190612bc7565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff81111561085357610852612bf7565b5b6040519080825280602002602001820160405280156108815781602001602082028036833780820191505090505b50905060005b7f00000000000000000000000000000000000000000000000000000000000000008110156108e457670de0b6b3a76400008282815181106108cb576108ca612c26565b5b6020026020010181815250508080600101915050610887565b5090565b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b83839050811015610a2c57610a118484838181106109f7576109f6612c26565b5b9050602002016020810190610a0c919061279b565b61182e565b610a1f576000915050610a32565b80806001019150506109d6565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a778261182e565b610a82576000610a8c565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b732f85824b2b38f179e451988670935d315b5b969281565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b73fed95453678920c1b7b3a81f033ca02a2722555681565b73777fba3666fa7747476a34577fccc404b263e09f81565b6000610bde8261182e565b610be9576000610bf3565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b73220230eda8f50067dd9e4729345dabcce0c6154281565b73a7241994267682de4de7ef62f52dc2c783d1784b81565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610d14611dae565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73281754ab58391a478b7aa4e7f39991cfb41118c481565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b736eed457c20603edae50c3a112caa1a9425321bd081565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b565b73b9c63a350a04d8bd245d18928a26ee036352ddd881565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610eb3611dae565b8281518110610ec557610ec4612c26565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f5f57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611829565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fe657826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611829565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361106d57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611829565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110d75782604051806060016040528060228152602001612c796022913991509150611829565b73220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361115e57826040518060400160405280601981526020017f68747470733a2f2f756d622e7374616b6572732e776f726c640000000000000081525091509150611829565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111e557826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611829565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361124f5782604051806060016040528060238152602001612c566023913991509150611829565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112d657826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611829565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113405782604051806060016040528060278152602001612cbf6027913991509150611829565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113c757826040518060400160405280601881526020017f68747470733a2f2f756d622e68617368717561726b2e696f000000000000000081525091509150611829565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114315782604051806060016040528060248152602001612c9b6024913991509150611829565b73b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361149b5782604051806060016040528060258152602001612ce66025913991509150611829565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152257826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611829565b73777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361158c5782604051806060016040528060278152602001612d2e6027913991509150611829565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361161357826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611829565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361169a57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611829565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036117045782604051806060016040528060238152602001612d0b6023913991509150611829565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361178b57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611829565b73fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361181257826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612d6e6f64652e636d7431332e6575000081525091509150611829565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806118bd575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061190757507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611951575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061199b575073220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806119e557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a2f575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a7957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ac3575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b0d5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b57575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ba1575073b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611beb57507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c35575073777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c7f5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611cc9575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d135750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d5d575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611da7575073fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff811115611dec57611deb612bf7565b5b604051908082528060200260200182016040528015611e1a5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611e4657611e45612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611ea957611ea8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611f0c57611f0b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611f6f57611f6e612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073220230eda8f50067dd9e4729345dabcce0c6154281600481518110611fd257611fd1612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac8160058151811061203557612034612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a388160068151811061209857612097612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa4719653111816007815181106120fb576120fa612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b8160088151811061215e5761215d612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff27144816009815181106121c1576121c0612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600a8151811061222457612223612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073b9c63a350a04d8bd245d18928a26ee036352ddd881600b8151811061228757612286612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600c815181106122ea576122e9612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073777fba3666fa7747476a34577fccc404b263e09f81600d8151811061234d5761234c612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600e815181106123b0576123af612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600f8151811061241357612412612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd08160108151811061247657612475612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb816011815181106124d9576124d8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073fed95453678920c1b7b3a81f033ca02a272255568160128151811061253c5761253b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6125bc816125a9565b82525050565b60006125ce83836125b3565b60208301905092915050565b6000602082019050919050565b60006125f28261257d565b6125fc8185612588565b935061260783612599565b8060005b8381101561263857815161261f88826125c2565b975061262a836125da565b92505060018101905061260b565b5085935050505092915050565b6000602082019050818103600083015261265f81846125e7565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061269282612667565b9050919050565b6126a281612687565b82525050565b60006020820190506126bd6000830184612699565b92915050565b600080fd5b600080fd5b6126d681612687565b81146126e157600080fd5b50565b6000813590506126f3816126cd565b92915050565b612702816125a9565b811461270d57600080fd5b50565b60008135905061271f816126f9565b92915050565b6000806040838503121561273c5761273b6126c3565b5b600061274a858286016126e4565b925050602061275b85828601612710565b9150509250929050565b60008115159050919050565b61277a81612765565b82525050565b60006020820190506127956000830184612771565b92915050565b6000602082840312156127b1576127b06126c3565b5b60006127bf848285016126e4565b91505092915050565b6000819050919050565b6127db816127c8565b82525050565b60006020820190506127f660008301846127d2565b92915050565b612805816125a9565b82525050565b600060208201905061282060008301846127fc565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261284b5761284a612826565b5b8235905067ffffffffffffffff8111156128685761286761282b565b5b60208301915083602082028301111561288457612883612830565b5b9250929050565b600080602083850312156128a2576128a16126c3565b5b600083013567ffffffffffffffff8111156128c0576128bf6126c8565b5b6128cc85828601612835565b92509250509250929050565b6000806000606084860312156128f1576128f06126c3565b5b60006128ff868287016126e4565b9350506020612910868287016126e4565b925050604061292186828701612710565b9150509250925092565b600060208284031215612941576129406126c3565b5b600061294f84828501612710565b91505092915050565b60008083601f84011261296e5761296d612826565b5b8235905067ffffffffffffffff81111561298b5761298a61282b565b5b6020830191508360018202830111156129a7576129a6612830565b5b9250929050565b6000806000604084860312156129c7576129c66126c3565b5b60006129d5868287016126e4565b935050602084013567ffffffffffffffff8111156129f6576129f56126c8565b5b612a0286828701612958565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b612a4381612687565b82525050565b6000612a558383612a3a565b60208301905092915050565b6000602082019050919050565b6000612a7982612a0e565b612a838185612a19565b9350612a8e83612a2a565b8060005b83811015612abf578151612aa68882612a49565b9750612ab183612a61565b925050600181019050612a92565b5085935050505092915050565b60006020820190508181036000830152612ae68184612a6e565b905092915050565b60008060408385031215612b0557612b046126c3565b5b6000612b13858286016126e4565b9250506020612b24858286016126e4565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612b68578082015181840152602081019050612b4d565b83811115612b77576000848401525b50505050565b6000601f19601f8301169050919050565b6000612b9982612b2e565b612ba38185612b39565b9350612bb3818560208601612b4a565b612bbc81612b7d565b840191505092915050565b6000604082019050612bdc6000830185612699565b8181036020830152612bee8184612b8e565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6170692e76616c696461747269756d2e636c756268747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6d68747470733a2f2f756d626e6f64652e626c6f636b636861696e6c69766572706f6f6c2e636f6da26469706673582212209a1752a9ea487818b8a4d658f151da9487c0cc92638142159bacde7ec2d21f7564736f6c634300080d0033", + "numDeployments": 4, + "solcInputHash": "dc68422c0ad35a4fe46d461b096b9383", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_validatorsCount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"NotSupported\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"minAmountForStake\",\"type\":\"uint256\"}],\"name\":\"LogMinAmountForStake\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"NUMBER_OF_VALIDATORS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ONE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TOTAL_SUPPLY\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_0\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_1\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_10\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_11\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_12\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_13\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_14\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_2\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_3\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_4\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_5\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_6\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_7\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_8\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_9\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_ix\",\"type\":\"uint256\"}],\"name\":\"addresses\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validator\",\"type\":\"address\"}],\"name\":\"balances\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"create\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"exit\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBalances\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"allBalances\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumberOfValidators\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"receiveApproval\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"register\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"remove\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"setMinAmountForStake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"stake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"update\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_id\",\"type\":\"address\"}],\"name\":\"validators\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"location\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_validators\",\"type\":\"address[]\"}],\"name\":\"verifyValidators\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addresses(uint256)\":{\"details\":\"gets validator address for provided index\",\"params\":{\"_ix\":\"index in array of list of all validators wallets\"}},\"balanceOf(address)\":{\"details\":\"to follow ERC20 interface\"},\"exit()\":{\"details\":\"unstake and withdraw all tokens\"},\"getName()\":{\"details\":\"to follow Registrable interface\"},\"getNumberOfValidators()\":{\"returns\":{\"_0\":\"total number of registered validators (with and without balance)\"}},\"register()\":{\"details\":\"to follow Registrable interface\"},\"totalSupply()\":{\"details\":\"to follow ERC20 interface\"},\"unregister()\":{\"details\":\"to follow Registrable interface\"},\"validators(address)\":{\"params\":{\"_id\":\"address of validator\"},\"returns\":{\"id\":\"address of validator\",\"location\":\"URL of validator\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":\"StakingBankStaticProd\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":0},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBank.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IStakingBank is IERC20 {\\n /// @param id address of validator wallet\\n /// @param location URL of the validator API\\n struct Validator {\\n address id;\\n string location;\\n }\\n\\n event LogValidatorRegistered(address indexed id);\\n event LogValidatorUpdated(address indexed id);\\n event LogValidatorRemoved(address indexed id);\\n event LogMinAmountForStake(uint256 minAmountForStake);\\n\\n /// @dev setter for `minAmountForStake`\\n function setMinAmountForStake(uint256 _minAmountForStake) external;\\n\\n /// @dev allows to stake `token` by validators\\n /// Validator needs to approve StakingBank beforehand\\n /// @param _value amount of tokens to stake\\n function stake(uint256 _value) external;\\n\\n /// @dev notification about approval from `_from` address on UMB token\\n /// Staking bank will stake max approved amount from `_from` address\\n /// @param _from address which approved token spend for IStakingBank\\n function receiveApproval(address _from) external returns (bool success);\\n\\n /// @dev withdraws stake tokens\\n /// it throws, when balance will be less than required minimum for stake\\n /// to withdraw all use `exit`\\n function withdraw(uint256 _value) external returns (bool success);\\n\\n /// @dev unstake and withdraw all tokens\\n function exit() external returns (bool success);\\n\\n /// @dev creates (register) new validator\\n /// @param _id validator address\\n /// @param _location location URL of the validator API\\n function create(address _id, string calldata _location) external;\\n\\n /// @dev removes validator\\n /// @param _id validator wallet\\n function remove(address _id) external;\\n\\n /// @dev updates validator location\\n /// @param _id validator wallet\\n /// @param _location new validator URL\\n function update(address _id, string calldata _location) external;\\n\\n /// @return total number of registered validators (with and without balance)\\n function getNumberOfValidators() external view returns (uint256);\\n\\n /// @dev gets validator address for provided index\\n /// @param _ix index in array of list of all validators wallets\\n function addresses(uint256 _ix) external view returns (address);\\n\\n /// @param _id address of validator\\n /// @return id address of validator\\n /// @return location URL of validator\\n function validators(address _id) external view returns (address id, string memory location);\\n}\\n\",\"keccak256\":\"0x2c518aeab8b0b3a364fafaec559d3ff0dc6a119f8d203fa31ef7ad667ca0f7b9\",\"license\":\"MIT\"},\"contracts/interfaces/StakingBankStaticNotSupported.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./IStakingBank.sol\\\";\\n\\nabstract contract StakingBankStaticNotSupported is IStakingBank {\\n error NotSupported();\\n\\n function create(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function update(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function remove(address) external pure {\\n revert NotSupported();\\n }\\n\\n function transfer(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function transferFrom(address, address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function receiveApproval(address) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function allowance(address, address) external pure returns (uint256) {\\n revert NotSupported();\\n }\\n\\n function approve(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function stake(uint256) external pure {\\n revert NotSupported();\\n }\\n\\n function withdraw(uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function exit() external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function setMinAmountForStake(uint256) external pure {\\n revert NotSupported();\\n }\\n}\\n\",\"keccak256\":\"0xa899ad9000220b04bc3f63f762a9a6a76dcc09449427e7774a53f4ceda9c1cf8\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStatic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"../interfaces/StakingBankStaticNotSupported.sol\\\";\\n\\n/// @dev Because we are using PoA in UMB oracle, staked balance does not matter. What's matter is, if signer is\\n/// validator or not. In this case we can optimise `StakingBank` and make it static for better gas performance.\\nabstract contract StakingBankStatic is StakingBankStaticNotSupported {\\n uint256 public constant ONE = 1e18;\\n\\n uint256 public immutable NUMBER_OF_VALIDATORS; // solhint-disable-line var-name-mixedcase\\n uint256 public immutable TOTAL_SUPPLY; // solhint-disable-line var-name-mixedcase\\n\\n constructor(uint256 _validatorsCount) {\\n NUMBER_OF_VALIDATORS = _validatorsCount;\\n TOTAL_SUPPLY = _validatorsCount * ONE;\\n\\n _assertValidSetup(_validatorsCount);\\n }\\n\\n function balances(address _validator) external view returns (uint256) {\\n return _isValidator(_validator) ? ONE : 0;\\n }\\n\\n function verifyValidators(address[] calldata _validators) external view returns (bool) {\\n for (uint256 i; i < _validators.length;) {\\n if (!_isValidator(_validators[i])) return false;\\n unchecked { i++; }\\n }\\n\\n return true;\\n }\\n\\n function getNumberOfValidators() external view returns (uint256) {\\n return NUMBER_OF_VALIDATORS;\\n }\\n\\n function getAddresses() external view returns (address[] memory) {\\n return _addresses();\\n }\\n\\n function getBalances() external view returns (uint256[] memory allBalances) {\\n allBalances = new uint256[](NUMBER_OF_VALIDATORS);\\n\\n for (uint256 i; i < NUMBER_OF_VALIDATORS;) {\\n allBalances[i] = ONE;\\n\\n unchecked {\\n // we will not have enough data to overflow\\n i++;\\n }\\n }\\n }\\n\\n function addresses(uint256 _ix) external view returns (address) {\\n return _addresses()[_ix];\\n }\\n\\n function validators(address _id) external view virtual returns (address id, string memory location);\\n\\n /// @dev to follow ERC20 interface\\n function balanceOf(address _account) external view returns (uint256) {\\n return _isValidator(_account) ? ONE : 0;\\n }\\n\\n /// @dev to follow ERC20 interface\\n function totalSupply() external view returns (uint256) {\\n return TOTAL_SUPPLY;\\n }\\n\\n /// @dev to follow Registrable interface\\n function getName() external pure returns (bytes32) {\\n return \\\"StakingBank\\\";\\n }\\n\\n /// @dev to follow Registrable interface\\n function register() external pure {\\n // there are no requirements atm\\n }\\n\\n /// @dev to follow Registrable interface\\n function unregister() external pure {\\n // there are no requirements atm\\n }\\n\\n function _addresses() internal view virtual returns (address[] memory);\\n\\n function _isValidator(address _validator) internal view virtual returns (bool);\\n\\n function _assertValidSetup(uint256 _validatorsCount) internal view virtual{\\n address[] memory list = _addresses();\\n require(list.length == _validatorsCount);\\n\\n for (uint256 i; i < _validatorsCount;) {\\n require(_isValidator(list[i]));\\n\\n unchecked { i ++; }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfcc53ff98b0f1c42e1bc7345a1535fdc4e938ef40d323600ead94b2ece59a381\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./StakingBankStatic.sol\\\";\\n\\ncontract StakingBankStaticProd is StakingBankStatic {\\n address public constant VALIDATOR_0 = 0x977Ba523420110e230643B772Fe9cF955e11dA7B;\\n address public constant VALIDATOR_1 = 0xe2422b23e52bc13ebA04d7FbB9F332Deb43360fB;\\n\\n // external order is based on validators submits on AVAX for Apr 2023\\n address public constant VALIDATOR_2 = 0x57F404aD75e371c1A539589C1eFCA12e0C6980AD;\\n address public constant VALIDATOR_3 = 0xD56C6A4f64E0bD70260472d1DB6Cf5825858CB0d;\\n address public constant VALIDATOR_4 = 0x93FdcAB283b0BcAc48157590af482E1CFd6af6aC;\\n address public constant VALIDATOR_5 = 0xCd733E06B06083d52fC5867E8E3432aA5c103A38;\\n address public constant VALIDATOR_6 = 0x42e210b110c6aa49CdfA7ceF1444Aa4719653111;\\n address public constant VALIDATOR_7 = 0x501731c6a69803a53Ec6c3e12f293c247cE1092B;\\n address public constant VALIDATOR_8 = 0x8bF9661F1b247522C75DD0FE84355aD2EfF27144;\\n address public constant VALIDATOR_9 = 0x281754Ab58391A478B7aA4E7f39991CfB41118c4;\\n address public constant VALIDATOR_10 = 0x57A51D5BDcE188c2295fCA3b4687475a54E65A02;\\n address public constant VALIDATOR_11 = 0x2F85824B2B38F179E451988670935d315b5b9692;\\n address public constant VALIDATOR_12 = 0xA7241994267682de4dE7Ef62f52dc2C783d1784B;\\n address public constant VALIDATOR_13 = 0x6eEd457C20603EDAE50C3A112CAA1a9425321bD0;\\n address public constant VALIDATOR_14 = 0xC5a7650c2725a7B6A39f15cb9FbffC7af357AFeb;\\n\\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\\n\\n // solhint-disable-next-line code-complexity\\n function validators(address _id) external pure override returns (address id, string memory location) {\\n if (_id == VALIDATOR_0) return (_id, \\\"https://validator.umb.network\\\");\\n if (_id == VALIDATOR_1) return (_id, \\\"https://validator2.umb.network\\\");\\n if (_id == VALIDATOR_2) return (_id, \\\"https://umbrella.artemahr.tech\\\");\\n if (_id == VALIDATOR_3) return (_id, \\\"https://umb.vtabsolutions.com:3030\\\");\\n if (_id == VALIDATOR_4) return (_id, \\\"https://umbrella.crazywhale.es\\\");\\n if (_id == VALIDATOR_5) return (_id, \\\"https://umbrella-node.gateomega.com\\\");\\n if (_id == VALIDATOR_6) return (_id, \\\"https://umb.anorak.technology\\\");\\n if (_id == VALIDATOR_7) return (_id, \\\"https://umbrella.validator.infstones.io\\\");\\n if (_id == VALIDATOR_8) return (_id, \\\"https://umb.hashkey.cloud\\\");\\n if (_id == VALIDATOR_9) return (_id, \\\"http://umbrella.staking4all.org:3000\\\");\\n if (_id == VALIDATOR_10) return (_id, \\\"http://5.161.78.230:3000\\\");\\n if (_id == VALIDATOR_11) return (_id, \\\"https://umb-api.staking.rocks\\\");\\n if (_id == VALIDATOR_12) return (_id, \\\"https://rpc.urbanhq.net\\\");\\n if (_id == VALIDATOR_13) return (_id, \\\"https://umbrella-node.ankastake.com\\\");\\n if (_id == VALIDATOR_14) return (_id, \\\"https://umbrella.tchambrella.com\\\");\\n\\n return (address(0), \\\"\\\");\\n }\\n\\n function _addresses() internal view override returns (address[] memory) {\\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\\n\\n list[0] = VALIDATOR_0;\\n list[1] = VALIDATOR_1;\\n list[2] = VALIDATOR_2;\\n list[3] = VALIDATOR_3;\\n list[4] = VALIDATOR_4;\\n list[5] = VALIDATOR_5;\\n list[6] = VALIDATOR_6;\\n list[7] = VALIDATOR_7;\\n list[8] = VALIDATOR_8;\\n list[9] = VALIDATOR_9;\\n list[10] = VALIDATOR_10;\\n list[11] = VALIDATOR_11;\\n list[12] = VALIDATOR_12;\\n list[13] = VALIDATOR_13;\\n list[14] = VALIDATOR_14;\\n\\n return list;\\n }\\n\\n function _isValidator(address _validator) internal pure override returns (bool) {\\n return (\\n _validator == VALIDATOR_0\\n || _validator == VALIDATOR_1\\n || _validator == VALIDATOR_2\\n || _validator == VALIDATOR_3\\n || _validator == VALIDATOR_4\\n || _validator == VALIDATOR_5\\n || _validator == VALIDATOR_6\\n || _validator == VALIDATOR_7\\n || _validator == VALIDATOR_8\\n || _validator == VALIDATOR_9\\n || _validator == VALIDATOR_10\\n || _validator == VALIDATOR_11\\n || _validator == VALIDATOR_12\\n || _validator == VALIDATOR_13\\n || _validator == VALIDATOR_14\\n );\\n }\\n}\\n\",\"keccak256\":\"0xcf8016c7d7325800fb6ac9f7afd34804b738daded6239139b23f894855a4f98b\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c06040523480156200001157600080fd5b50604051620034f8380380620034f8833981810160405281019062000037919062000beb565b808060808181525050670de0b6b3a76400008162000056919062000c4c565b60a081815250506200006e816200007660201b60201c565b505062000d0b565b600062000088620000ef60201b60201c565b9050818151146200009857600080fd5b60005b82811015620000ea57620000d2828281518110620000be57620000bd62000cad565b5b60200260200101516200074560201b60201c565b620000dc57600080fd5b80806001019150506200009b565b505050565b6060600060805167ffffffffffffffff81111562000112576200011162000cdc565b5b604051908082528060200260200182016040528015620001415781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b8160008151811062000170576200016f62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110620001d657620001d562000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad816002815181106200023c576200023b62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110620002a257620002a162000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac8160048151811062000308576200030762000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a38816005815181106200036e576200036d62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa471965311181600681518110620003d457620003d362000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b816007815181106200043a576200043962000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff2714481600881518110620004a0576200049f62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c48160098151811062000506576200050562000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600a815181106200056c576200056b62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600b81518110620005d257620005d162000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600c8151811062000638576200063762000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081600d815181106200069e576200069d62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81600e8151811062000704576200070362000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480620007d5575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806200082057507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806200086b575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80620008b657507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000901575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806200094c57507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000997575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80620009e25750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a2d575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a7857507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ac35750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b0e575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b595750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ba4575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b600080fd5b6000819050919050565b62000bc58162000bb0565b811462000bd157600080fd5b50565b60008151905062000be58162000bba565b92915050565b60006020828403121562000c045762000c0362000bab565b5b600062000c148482850162000bd4565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600062000c598262000bb0565b915062000c668362000bb0565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161562000ca25762000ca162000c1d565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60805160a0516127a462000d54600039600081816109080152610b72015260008181610777015281816107e501528181610b9801528181610ce901526119a601526127a46000f3fe608060405234801561001057600080fd5b50600436106101ed5760003560e01c8062113e08146101f2578063015f7ed61461021057806303a1e2241461022e578063095ea7b31461024c5780630db18e371461027c57806317d7de7c146102ac57806318160ddd146102ca5780631aa3a008146102e85780631d4f9ce0146102f257806323b872dd1461032257806327e235e31461035257806329092d0e146103825780632e1a7d4d1461039e578063398b056e146103ce578063411ff497146103ec57806345f9f8251461040a57806352b41e351461042857806354755335146104445780635dc4bfd31461046257806369dc7ae41461048057806370a082311461049e578063838e7c3a146104ce578063902d55a5146104ea5780639031d9131461050857806390ff7e2e14610526578063989b6996146105445780639f0e948414610562578063a15ab08d14610580578063a39fac121461059c578063a694fc3a146105ba578063a9059cbb146105d6578063b2119eac14610606578063b49b084214610624578063c2ee3a0814610642578063db73177714610660578063dd62ed3e1461067e578063e2dc7a1a146106ae578063e79a198f146106cc578063e985e008146106d6578063e9fad8ee146106f4578063edf26d9b14610712578063fa52c7d814610742575b600080fd5b6101fa610773565b60405161020791906120ab565b60405180910390f35b610218610844565b604051610225919061210e565b60405180910390f35b61023661085c565b604051610243919061210e565b60405180910390f35b6102666004803603810190610261919061218b565b610874565b60405161027391906121e6565b60405180910390f35b61029660048036038101906102919190612201565b6108a8565b6040516102a391906121e6565b60405180910390f35b6102b46108dc565b6040516102c19190612247565b60405180910390f35b6102d2610904565b6040516102df9190612271565b60405180910390f35b6102f061092c565b005b61030c600480360381019061030791906122f1565b61092e565b60405161031991906121e6565b60405180910390f35b61033c6004803603810190610337919061233e565b610994565b60405161034991906121e6565b60405180910390f35b61036c60048036038101906103679190612201565b6109c8565b6040516103799190612271565b60405180910390f35b61039c60048036038101906103979190612201565b6109ef565b005b6103b860048036038101906103b39190612391565b610a21565b6040516103c591906121e6565b60405180910390f35b6103d6610a55565b6040516103e3919061210e565b60405180910390f35b6103f4610a6d565b604051610401919061210e565b60405180910390f35b610412610a85565b60405161041f919061210e565b60405180910390f35b610442600480360381019061043d9190612391565b610a9d565b005b61044c610acf565b604051610459919061210e565b60405180910390f35b61046a610ae7565b604051610477919061210e565b60405180910390f35b610488610aff565b604051610495919061210e565b60405180910390f35b6104b860048036038101906104b39190612201565b610b17565b6040516104c59190612271565b60405180910390f35b6104e860048036038101906104e39190612414565b610b3e565b005b6104f2610b70565b6040516104ff9190612271565b60405180910390f35b610510610b94565b60405161051d9190612271565b60405180910390f35b61052e610bbc565b60405161053b919061210e565b60405180910390f35b61054c610bd4565b604051610559919061210e565b60405180910390f35b61056a610bec565b604051610577919061210e565b60405180910390f35b61059a60048036038101906105959190612414565b610c04565b005b6105a4610c36565b6040516105b19190612532565b60405180910390f35b6105d460048036038101906105cf9190612391565b610c45565b005b6105f060048036038101906105eb919061218b565b610c77565b6040516105fd91906121e6565b60405180910390f35b61060e610cab565b60405161061b919061210e565b60405180910390f35b61062c610cc3565b604051610639919061210e565b60405180910390f35b61064a610cdb565b6040516106579190612271565b60405180910390f35b610668610ce7565b6040516106759190612271565b60405180910390f35b61069860048036038101906106939190612554565b610d0b565b6040516106a59190612271565b60405180910390f35b6106b6610d3f565b6040516106c3919061210e565b60405180910390f35b6106d4610d57565b005b6106de610d59565b6040516106eb919061210e565b60405180910390f35b6106fc610d71565b60405161070991906121e6565b60405180910390f35b61072c60048036038101906107279190612391565b610da5565b604051610739919061210e565b60405180910390f35b61075c60048036038101906107579190612201565b610dd0565b60405161076a92919061262d565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156107af576107ae61265d565b5b6040519080825280602002602001820160405280156107dd5781602001602082028036833780820191505090505b50905060005b7f000000000000000000000000000000000000000000000000000000000000000081101561084057670de0b6b3a76400008282815181106108275761082661268c565b5b60200260200101818152505080806001019150506107e3565b5090565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b838390508110156109885761096d8484838181106109535761095261268c565b5b90506020020160208101906109689190612201565b611548565b61097b57600091505061098e565b8080600101915050610932565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006109d382611548565b6109de5760006109e8565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73a7241994267682de4de7ef62f52dc2c783d1784b81565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b736eed457c20603edae50c3a112caa1a9425321bd081565b6000610b2282611548565b610b2d576000610b37565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73281754ab58391a478b7aa4e7f39991cfb41118c481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610c406119a0565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b565b732f85824b2b38f179e451988670935d315b5b969281565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610daf6119a0565b8281518110610dc157610dc061268c565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e5b57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611543565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610ee257826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611543565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f6957826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611543565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fd357826040518060600160405280602281526020016126df6022913991509150611543565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361105a57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611543565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110c457826040518060600160405280602381526020016126bc6023913991509150611543565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361114b57826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611543565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111b557826040518060600160405280602781526020016127256027913991509150611543565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361123c57826040518060400160405280601981526020017f68747470733a2f2f756d622e686173686b65792e636c6f75640000000000000081525091509150611543565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112a657826040518060600160405280602481526020016127016024913991509150611543565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361132d57826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611543565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113b457826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611543565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361143b57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611543565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114a5578260405180606001604052806023815260200161274c6023913991509150611543565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152c57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611543565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806115d7575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061162157507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061166b575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116b557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116ff575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061174957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611793575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806117dd5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611827575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061187157507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806118bb5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611905575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061194f5750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611999575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156119de576119dd61265d565b5b604051908082528060200260200182016040528015611a0c5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611a3857611a3761268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611a9b57611a9a61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611afe57611afd61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611b6157611b6061268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac81600481518110611bc457611bc361268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a3881600581518110611c2757611c2661268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa471965311181600681518110611c8a57611c8961268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b81600781518110611ced57611cec61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff2714481600881518110611d5057611d4f61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600981518110611db357611db261268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600a81518110611e1657611e1561268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600b81518110611e7957611e7861268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600c81518110611edc57611edb61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081600d81518110611f3f57611f3e61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81600e81518110611fa257611fa161268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6120228161200f565b82525050565b60006120348383612019565b60208301905092915050565b6000602082019050919050565b600061205882611fe3565b6120628185611fee565b935061206d83611fff565b8060005b8381101561209e5781516120858882612028565b975061209083612040565b925050600181019050612071565b5085935050505092915050565b600060208201905081810360008301526120c5818461204d565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006120f8826120cd565b9050919050565b612108816120ed565b82525050565b600060208201905061212360008301846120ff565b92915050565b600080fd5b600080fd5b61213c816120ed565b811461214757600080fd5b50565b60008135905061215981612133565b92915050565b6121688161200f565b811461217357600080fd5b50565b6000813590506121858161215f565b92915050565b600080604083850312156121a2576121a1612129565b5b60006121b08582860161214a565b92505060206121c185828601612176565b9150509250929050565b60008115159050919050565b6121e0816121cb565b82525050565b60006020820190506121fb60008301846121d7565b92915050565b60006020828403121561221757612216612129565b5b60006122258482850161214a565b91505092915050565b6000819050919050565b6122418161222e565b82525050565b600060208201905061225c6000830184612238565b92915050565b61226b8161200f565b82525050565b60006020820190506122866000830184612262565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126122b1576122b061228c565b5b8235905067ffffffffffffffff8111156122ce576122cd612291565b5b6020830191508360208202830111156122ea576122e9612296565b5b9250929050565b6000806020838503121561230857612307612129565b5b600083013567ffffffffffffffff8111156123265761232561212e565b5b6123328582860161229b565b92509250509250929050565b60008060006060848603121561235757612356612129565b5b60006123658682870161214a565b93505060206123768682870161214a565b925050604061238786828701612176565b9150509250925092565b6000602082840312156123a7576123a6612129565b5b60006123b584828501612176565b91505092915050565b60008083601f8401126123d4576123d361228c565b5b8235905067ffffffffffffffff8111156123f1576123f0612291565b5b60208301915083600182028301111561240d5761240c612296565b5b9250929050565b60008060006040848603121561242d5761242c612129565b5b600061243b8682870161214a565b935050602084013567ffffffffffffffff81111561245c5761245b61212e565b5b612468868287016123be565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6124a9816120ed565b82525050565b60006124bb83836124a0565b60208301905092915050565b6000602082019050919050565b60006124df82612474565b6124e9818561247f565b93506124f483612490565b8060005b8381101561252557815161250c88826124af565b9750612517836124c7565b9250506001810190506124f8565b5085935050505092915050565b6000602082019050818103600083015261254c81846124d4565b905092915050565b6000806040838503121561256b5761256a612129565b5b60006125798582860161214a565b925050602061258a8582860161214a565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156125ce5780820151818401526020810190506125b3565b838111156125dd576000848401525b50505050565b6000601f19601f8301169050919050565b60006125ff82612594565b612609818561259f565b93506126198185602086016125b0565b612622816125e3565b840191505092915050565b600060408201905061264260008301856120ff565b818103602083015261265481846125f4565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6da2646970667358221220b875faa4ff94a6ed380db1c82cfc4fcfdce28d00988b3f85c113e0332affbaa264736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101ed5760003560e01c8062113e08146101f2578063015f7ed61461021057806303a1e2241461022e578063095ea7b31461024c5780630db18e371461027c57806317d7de7c146102ac57806318160ddd146102ca5780631aa3a008146102e85780631d4f9ce0146102f257806323b872dd1461032257806327e235e31461035257806329092d0e146103825780632e1a7d4d1461039e578063398b056e146103ce578063411ff497146103ec57806345f9f8251461040a57806352b41e351461042857806354755335146104445780635dc4bfd31461046257806369dc7ae41461048057806370a082311461049e578063838e7c3a146104ce578063902d55a5146104ea5780639031d9131461050857806390ff7e2e14610526578063989b6996146105445780639f0e948414610562578063a15ab08d14610580578063a39fac121461059c578063a694fc3a146105ba578063a9059cbb146105d6578063b2119eac14610606578063b49b084214610624578063c2ee3a0814610642578063db73177714610660578063dd62ed3e1461067e578063e2dc7a1a146106ae578063e79a198f146106cc578063e985e008146106d6578063e9fad8ee146106f4578063edf26d9b14610712578063fa52c7d814610742575b600080fd5b6101fa610773565b60405161020791906120ab565b60405180910390f35b610218610844565b604051610225919061210e565b60405180910390f35b61023661085c565b604051610243919061210e565b60405180910390f35b6102666004803603810190610261919061218b565b610874565b60405161027391906121e6565b60405180910390f35b61029660048036038101906102919190612201565b6108a8565b6040516102a391906121e6565b60405180910390f35b6102b46108dc565b6040516102c19190612247565b60405180910390f35b6102d2610904565b6040516102df9190612271565b60405180910390f35b6102f061092c565b005b61030c600480360381019061030791906122f1565b61092e565b60405161031991906121e6565b60405180910390f35b61033c6004803603810190610337919061233e565b610994565b60405161034991906121e6565b60405180910390f35b61036c60048036038101906103679190612201565b6109c8565b6040516103799190612271565b60405180910390f35b61039c60048036038101906103979190612201565b6109ef565b005b6103b860048036038101906103b39190612391565b610a21565b6040516103c591906121e6565b60405180910390f35b6103d6610a55565b6040516103e3919061210e565b60405180910390f35b6103f4610a6d565b604051610401919061210e565b60405180910390f35b610412610a85565b60405161041f919061210e565b60405180910390f35b610442600480360381019061043d9190612391565b610a9d565b005b61044c610acf565b604051610459919061210e565b60405180910390f35b61046a610ae7565b604051610477919061210e565b60405180910390f35b610488610aff565b604051610495919061210e565b60405180910390f35b6104b860048036038101906104b39190612201565b610b17565b6040516104c59190612271565b60405180910390f35b6104e860048036038101906104e39190612414565b610b3e565b005b6104f2610b70565b6040516104ff9190612271565b60405180910390f35b610510610b94565b60405161051d9190612271565b60405180910390f35b61052e610bbc565b60405161053b919061210e565b60405180910390f35b61054c610bd4565b604051610559919061210e565b60405180910390f35b61056a610bec565b604051610577919061210e565b60405180910390f35b61059a60048036038101906105959190612414565b610c04565b005b6105a4610c36565b6040516105b19190612532565b60405180910390f35b6105d460048036038101906105cf9190612391565b610c45565b005b6105f060048036038101906105eb919061218b565b610c77565b6040516105fd91906121e6565b60405180910390f35b61060e610cab565b60405161061b919061210e565b60405180910390f35b61062c610cc3565b604051610639919061210e565b60405180910390f35b61064a610cdb565b6040516106579190612271565b60405180910390f35b610668610ce7565b6040516106759190612271565b60405180910390f35b61069860048036038101906106939190612554565b610d0b565b6040516106a59190612271565b60405180910390f35b6106b6610d3f565b6040516106c3919061210e565b60405180910390f35b6106d4610d57565b005b6106de610d59565b6040516106eb919061210e565b60405180910390f35b6106fc610d71565b60405161070991906121e6565b60405180910390f35b61072c60048036038101906107279190612391565b610da5565b604051610739919061210e565b60405180910390f35b61075c60048036038101906107579190612201565b610dd0565b60405161076a92919061262d565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156107af576107ae61265d565b5b6040519080825280602002602001820160405280156107dd5781602001602082028036833780820191505090505b50905060005b7f000000000000000000000000000000000000000000000000000000000000000081101561084057670de0b6b3a76400008282815181106108275761082661268c565b5b60200260200101818152505080806001019150506107e3565b5090565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b838390508110156109885761096d8484838181106109535761095261268c565b5b90506020020160208101906109689190612201565b611548565b61097b57600091505061098e565b8080600101915050610932565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006109d382611548565b6109de5760006109e8565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73a7241994267682de4de7ef62f52dc2c783d1784b81565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b736eed457c20603edae50c3a112caa1a9425321bd081565b6000610b2282611548565b610b2d576000610b37565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73281754ab58391a478b7aa4e7f39991cfb41118c481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610c406119a0565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b565b732f85824b2b38f179e451988670935d315b5b969281565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610daf6119a0565b8281518110610dc157610dc061268c565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e5b57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611543565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610ee257826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611543565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f6957826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611543565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fd357826040518060600160405280602281526020016126df6022913991509150611543565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361105a57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611543565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110c457826040518060600160405280602381526020016126bc6023913991509150611543565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361114b57826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611543565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111b557826040518060600160405280602781526020016127256027913991509150611543565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361123c57826040518060400160405280601981526020017f68747470733a2f2f756d622e686173686b65792e636c6f75640000000000000081525091509150611543565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112a657826040518060600160405280602481526020016127016024913991509150611543565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361132d57826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611543565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113b457826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611543565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361143b57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611543565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114a5578260405180606001604052806023815260200161274c6023913991509150611543565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152c57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611543565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806115d7575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061162157507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061166b575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116b557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116ff575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061174957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611793575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806117dd5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611827575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061187157507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806118bb5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611905575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061194f5750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611999575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156119de576119dd61265d565b5b604051908082528060200260200182016040528015611a0c5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611a3857611a3761268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611a9b57611a9a61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611afe57611afd61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611b6157611b6061268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac81600481518110611bc457611bc361268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a3881600581518110611c2757611c2661268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa471965311181600681518110611c8a57611c8961268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b81600781518110611ced57611cec61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff2714481600881518110611d5057611d4f61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600981518110611db357611db261268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600a81518110611e1657611e1561268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600b81518110611e7957611e7861268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600c81518110611edc57611edb61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081600d81518110611f3f57611f3e61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81600e81518110611fa257611fa161268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6120228161200f565b82525050565b60006120348383612019565b60208301905092915050565b6000602082019050919050565b600061205882611fe3565b6120628185611fee565b935061206d83611fff565b8060005b8381101561209e5781516120858882612028565b975061209083612040565b925050600181019050612071565b5085935050505092915050565b600060208201905081810360008301526120c5818461204d565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006120f8826120cd565b9050919050565b612108816120ed565b82525050565b600060208201905061212360008301846120ff565b92915050565b600080fd5b600080fd5b61213c816120ed565b811461214757600080fd5b50565b60008135905061215981612133565b92915050565b6121688161200f565b811461217357600080fd5b50565b6000813590506121858161215f565b92915050565b600080604083850312156121a2576121a1612129565b5b60006121b08582860161214a565b92505060206121c185828601612176565b9150509250929050565b60008115159050919050565b6121e0816121cb565b82525050565b60006020820190506121fb60008301846121d7565b92915050565b60006020828403121561221757612216612129565b5b60006122258482850161214a565b91505092915050565b6000819050919050565b6122418161222e565b82525050565b600060208201905061225c6000830184612238565b92915050565b61226b8161200f565b82525050565b60006020820190506122866000830184612262565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126122b1576122b061228c565b5b8235905067ffffffffffffffff8111156122ce576122cd612291565b5b6020830191508360208202830111156122ea576122e9612296565b5b9250929050565b6000806020838503121561230857612307612129565b5b600083013567ffffffffffffffff8111156123265761232561212e565b5b6123328582860161229b565b92509250509250929050565b60008060006060848603121561235757612356612129565b5b60006123658682870161214a565b93505060206123768682870161214a565b925050604061238786828701612176565b9150509250925092565b6000602082840312156123a7576123a6612129565b5b60006123b584828501612176565b91505092915050565b60008083601f8401126123d4576123d361228c565b5b8235905067ffffffffffffffff8111156123f1576123f0612291565b5b60208301915083600182028301111561240d5761240c612296565b5b9250929050565b60008060006040848603121561242d5761242c612129565b5b600061243b8682870161214a565b935050602084013567ffffffffffffffff81111561245c5761245b61212e565b5b612468868287016123be565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6124a9816120ed565b82525050565b60006124bb83836124a0565b60208301905092915050565b6000602082019050919050565b60006124df82612474565b6124e9818561247f565b93506124f483612490565b8060005b8381101561252557815161250c88826124af565b9750612517836124c7565b9250506001810190506124f8565b5085935050505092915050565b6000602082019050818103600083015261254c81846124d4565b905092915050565b6000806040838503121561256b5761256a612129565b5b60006125798582860161214a565b925050602061258a8582860161214a565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156125ce5780820151818401526020810190506125b3565b838111156125dd576000848401525b50505050565b6000601f19601f8301169050919050565b60006125ff82612594565b612609818561259f565b93506126198185602086016125b0565b612622816125e3565b840191505092915050565b600060408201905061264260008301856120ff565b818103602083015261265481846125f4565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6da2646970667358221220b875faa4ff94a6ed380db1c82cfc4fcfdce28d00988b3f85c113e0332affbaa264736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/bnb_production/solcInputs/dc68422c0ad35a4fe46d461b096b9383.json b/deployments/bnb_production/solcInputs/dc68422c0ad35a4fe46d461b096b9383.json new file mode 100644 index 00000000..43238985 --- /dev/null +++ b/deployments/bnb_production/solcInputs/dc68422c0ad35a4fe46d461b096b9383.json @@ -0,0 +1,125 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n }\n _balances[to] += amount;\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n _balances[account] += amount;\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n }\n _totalSupply -= amount;\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Trees proofs.\n *\n * The proofs can be generated using the JavaScript library\n * https://github.com/miguelmota/merkletreejs[merkletreejs].\n * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.\n *\n * See `test/utils/cryptography/MerkleProof.test.js` for some examples.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(\n bytes32[] memory proof,\n bytes32 root,\n bytes32 leaf\n ) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n bytes32 proofElement = proof[i];\n if (computedHash <= proofElement) {\n // Hash(current computed hash + current element of the proof)\n computedHash = _efficientHash(computedHash, proofElement);\n } else {\n // Hash(current element of the proof + current computed hash)\n computedHash = _efficientHash(proofElement, computedHash);\n }\n }\n return computedHash;\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "@umb-network/toolbox/dist/contracts/lib/ValueDecoder.sol": { + "content": "//SPDX-License-Identifier: Unlicensed\npragma solidity >=0.6.8;\n\nlibrary ValueDecoder {\n function toUint(bytes memory _bytes) internal pure returns (uint256 value) {\n assembly {\n value := mload(add(_bytes, 32))\n }\n }\n\n function toUint(bytes32 _bytes) internal pure returns (uint256 value) {\n assembly {\n value := _bytes\n }\n }\n\n function toInt(uint224 u) internal pure returns (int256) {\n int224 i;\n uint224 max = type(uint224).max;\n\n if (u <= (max - 1) / 2) { // positive values\n assembly {\n i := add(u, 0)\n }\n\n return i;\n } else { // negative values\n assembly {\n i := sub(sub(u, max), 1)\n }\n }\n\n return i;\n }\n}\n\n" + }, + "contracts/BaseChain.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\";\nimport \"@umb-network/toolbox/dist/contracts/lib/ValueDecoder.sol\";\n\nimport \"./interfaces/IBaseChainV1.sol\";\nimport \"./interfaces/IStakingBank.sol\";\nimport \"./extensions/Registrable.sol\";\nimport \"./Registry.sol\";\n\nabstract contract BaseChain is Registrable, Ownable {\n using ValueDecoder for bytes;\n using ValueDecoder for uint224;\n using MerkleProof for bytes32[];\n\n /// @param root merkle root for consensus\n /// @param dataTimestamp consensus timestamp\n struct Block {\n bytes32 root;\n uint32 dataTimestamp;\n }\n\n /// @param value FCD value\n /// @param dataTimestamp FCD timestamp\n struct FirstClassData {\n uint224 value;\n uint32 dataTimestamp;\n }\n\n /// @param blocksCountOffset number of all blocks that were generated before switching to this contract\n /// @param sequence is a total number of blocks (consensus rounds) including previous contracts\n /// @param lastTimestamp is a timestamp of last submitted block\n /// @param padding number of seconds that need to pass before new submit will be possible\n /// @param deprecated flag that changes to TRUE on `unregister`, when TRUE submissions are not longer available\n struct ConsensusData {\n uint32 blocksCountOffset;\n uint32 sequence;\n uint32 lastTimestamp;\n uint32 padding;\n bool deprecated;\n }\n\n uint256 constant public VERSION = 2;\n\n bool internal immutable _ALLOW_FOR_MIXED_TYPE; // solhint-disable-line var-name-mixedcase\n\n bytes4 constant private _VERSION_SELECTOR = bytes4(keccak256(\"VERSION()\"));\n\n /// @dev minimal number of signatures required for accepting submission (PoA)\n uint16 internal immutable _REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\n\n ConsensusData internal _consensusData;\n\n bytes constant public ETH_PREFIX = \"\\x19Ethereum Signed Message:\\n32\";\n\n /// @dev block id (consensus ID) => root\n /// consensus ID is at the same time consensus timestamp\n mapping(uint256 => bytes32) public roots;\n\n /// @dev FCD key => FCD data\n mapping(bytes32 => FirstClassData) public fcds;\n\n event LogDeprecation(address indexed deprecator);\n event LogPadding(address indexed executor, uint32 timePadding);\n\n error ArraysDataDoNotMatch();\n error AlreadyDeprecated();\n error AlreadyRegistered();\n error BlockSubmittedToFastOrDataToOld();\n error ContractNotReady();\n error FCDOverflow();\n error InvalidContractType();\n error NoChangeToState();\n error OnlyOwnerOrRegistry();\n error UnregisterFirst();\n\n modifier onlyOwnerOrRegistry () {\n if (msg.sender != address(contractRegistry) && msg.sender != owner()) revert OnlyOwnerOrRegistry();\n _;\n }\n\n /// @param _contractRegistry Registry address\n /// @param _padding required \"space\" between blocks in seconds\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n constructor(\n IRegistry _contractRegistry,\n uint32 _padding,\n uint16 _requiredSignatures,\n bool _allowForMixedType\n ) Registrable(_contractRegistry) {\n _ALLOW_FOR_MIXED_TYPE = _allowForMixedType;\n _REQUIRED_SIGNATURES = _requiredSignatures;\n\n _setPadding(_padding);\n\n BaseChain oldChain = BaseChain(_contractRegistry.getAddress(\"Chain\"));\n\n if (address(oldChain) == address(0)) {\n // if this is first contract in sidechain, then we need to initialise lastTimestamp so submission\n // can be possible\n _consensusData.lastTimestamp = uint32(block.timestamp) - _padding - 1;\n }\n }\n\n /// @dev setter for `padding`\n function setPadding(uint16 _padding) external {\n _setPadding(_padding);\n }\n\n /// @notice if this method needs to be called manually (not from Registry)\n /// it is important to do it as part of tx batch\n /// eg using multisig, we should prepare set of transactions and confirm them all at once\n /// @inheritdoc Registrable\n function register() external override onlyOwnerOrRegistry {\n address oldChain = contractRegistry.getAddress(\"Chain\");\n\n // registration must be done before address in registry is replaced\n if (oldChain == address(this)) revert AlreadyRegistered();\n\n if (oldChain == address(0x0)) {\n return;\n }\n\n _cloneLastDataFromPrevChain(oldChain);\n }\n\n /// @inheritdoc Registrable\n function unregister() external override onlyOwnerOrRegistry {\n // in case we deprecated contract manually, we simply return\n if (_consensusData.deprecated) return;\n\n address newChain = contractRegistry.getAddress(\"Chain\");\n // unregistering must be done after address in registry is replaced\n if (newChain == address(this)) revert UnregisterFirst();\n\n // TODO:\n // I think we need to remove restriction for type (at least once)\n // when we will switch to multichain architecture\n\n if (!_ALLOW_FOR_MIXED_TYPE) {\n // can not be replaced with chain of different type\n if (BaseChain(newChain).isForeign() != this.isForeign()) revert InvalidContractType();\n }\n\n _consensusData.deprecated = true;\n emit LogDeprecation(msg.sender);\n }\n\n /// @notice it allows to deprecate contract manually\n /// Only new Registry calls `unregister()` where we set deprecated to true\n /// In old Registries we don't have this feature, so in order to safely redeploy new Chain\n /// we will have to first deprecate current contract manually, then register new contract\n function deprecate() external onlyOwnerOrRegistry {\n if (_consensusData.deprecated) revert AlreadyDeprecated();\n\n _consensusData.deprecated = true;\n emit LogDeprecation(msg.sender);\n }\n\n /// @dev getter for `_consensusData`\n function getConsensusData() external view returns (ConsensusData memory) {\n return _consensusData;\n }\n\n /// @dev number of blocks (consensus rounds) saved in this contract\n function blocksCount() external view returns (uint256) {\n return _consensusData.sequence - _consensusData.blocksCountOffset;\n }\n\n function blocksCountOffset() external view returns (uint32) {\n return _consensusData.blocksCountOffset;\n }\n\n function lastBlockId() external view returns (uint256) {\n return _consensusData.lastTimestamp;\n }\n\n /// @return TRUE if contract is ForeignChain, FALSE otherwise\n function isForeign() external pure virtual returns (bool);\n\n /// @inheritdoc Registrable\n function getName() external pure override returns (bytes32) {\n return \"Chain\";\n }\n\n /// @param _affidavit root and FCDs hashed together\n /// @param _v part of signature\n /// @param _r part of signature\n /// @param _s part of signature\n /// @return signer address\n function recoverSigner(bytes32 _affidavit, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _affidavit));\n return ecrecover(hash, _v, _r, _s);\n }\n\n /// @param _blockId ID of submitted block\n /// @return block data (root + timestamp)\n function blocks(uint256 _blockId) external view returns (Block memory) {\n return Block(roots[_blockId], uint32(_blockId));\n }\n\n /// @return current block ID\n /// please note, that current ID is not the same as last ID, current means that once padding pass,\n /// ID will switch to next one and it will be pointing to empty submit until submit for that ID is done\n function getBlockId() external view returns (uint32) {\n if (_consensusData.lastTimestamp == 0) return 0;\n\n return getBlockIdAtTimestamp(block.timestamp);\n }\n\n function requiredSignatures() external view returns (uint16) {\n return _REQUIRED_SIGNATURES;\n }\n\n /// @dev calculates block ID for provided timestamp\n /// this function does not works for past timestamps\n /// @param _timestamp current or future timestamp\n /// @return block ID for provided timestamp\n function getBlockIdAtTimestamp(uint256 _timestamp) virtual public view returns (uint32) {\n ConsensusData memory data = _consensusData;\n\n unchecked {\n // we can't overflow because we adding two `uint32`\n if (data.lastTimestamp + data.padding < _timestamp) {\n return uint32(_timestamp);\n }\n }\n\n return data.lastTimestamp;\n }\n\n /// @return last submitted block ID, please note, that on deployment, when there is no submission for this contract\n /// block for last ID will be available in previous contract\n function getLatestBlockId() virtual public view returns (uint32) {\n return _consensusData.lastTimestamp;\n }\n\n /// @dev verifies if the leaf is valid leaf for merkle tree\n /// @param _proof merkle proof for merkle tree\n /// @param _root merkle root\n /// @param _leaf leaf hash\n /// @return TRUE if `_leaf` is valid, FALSE otherwise\n function verifyProof(bytes32[] memory _proof, bytes32 _root, bytes32 _leaf) public pure returns (bool) {\n if (_root == bytes32(0)) {\n return false;\n }\n\n return _proof.verify(_root, _leaf);\n }\n\n /// @dev creates leaf hash, that has is used in merkle tree\n /// @param _key key under which we store the value\n /// @param _value value itself as bytes\n /// @return leaf hash\n function hashLeaf(bytes memory _key, bytes memory _value) public pure returns (bytes32) {\n return keccak256(abi.encodePacked(_key, _value));\n }\n\n /// @dev verifies, if provided key-value pair was part of consensus\n /// @param _blockId consensus ID for which we doing a check\n /// @param _proof merkle proof for pair\n /// @param _key pair key\n /// @param _value pair value\n /// @return TRUE if key-value par was part of consensus, FALSE otherwise\n function verifyProofForBlock(\n uint256 _blockId,\n bytes32[] memory _proof,\n bytes memory _key,\n bytes memory _value\n )\n public\n view\n returns (bool)\n {\n return _proof.verify(roots[_blockId], keccak256(abi.encodePacked(_key, _value)));\n }\n\n /// @dev this is helper method, that extracts one merkle proof from many hashed provided as bytes\n /// @param _data many hashes as bytes\n /// @param _offset this is starting point for extraction\n /// @param _items how many hashes to extract\n /// @return merkle proof (array of bytes32 hashes)\n function bytesToBytes32Array(\n bytes memory _data,\n uint256 _offset,\n uint256 _items\n )\n public\n pure\n returns (bytes32[] memory)\n {\n bytes32[] memory dataList = new bytes32[](_items);\n\n // we can unchecked because we working only with `i` and `_offset`\n // in case of wrong `_offset` it will throw\n unchecked {\n for (uint256 i = 0; i < _items; i++) {\n bytes32 temp;\n uint256 idx = (i + 1 + _offset) * 32;\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n temp := mload(add(_data, idx))\n }\n\n dataList[i] = temp;\n }\n }\n\n return (dataList);\n }\n\n /// @dev batch method for data verification\n /// @param _blockIds consensus IDs for which we doing a checks\n /// @param _proofs merkle proofs for all pair, sequence of hashes provided as bytes\n /// @param _proofItemsCounter array of counters, each counter tells how many hashes proof for each leaf has\n /// @param _leaves array of merkle leaves\n /// @return results array of verification results, TRUE if leaf is part of consensus, FALSE otherwise\n function verifyProofs(\n uint32[] memory _blockIds,\n bytes memory _proofs,\n uint256[] memory _proofItemsCounter,\n bytes32[] memory _leaves\n )\n public\n view\n returns (bool[] memory results)\n {\n results = new bool[](_leaves.length);\n uint256 offset = 0;\n\n for (uint256 i = 0; i < _leaves.length;) {\n results[i] = bytesToBytes32Array(_proofs, offset, _proofItemsCounter[i]).verify(\n roots[_blockIds[i]], _leaves[i]\n );\n\n unchecked {\n // we can uncheck because it will not overflow in a lifetime, and if someone provide invalid counter\n // we verification will not be valid (or we throw because of invalid memory access)\n offset += _proofItemsCounter[i];\n // we can uncheck because `i` will not overflow in a lifetime\n i++;\n }\n }\n }\n\n /// @param _blockId consensus ID\n /// @return root for provided consensus ID\n function getBlockRoot(uint32 _blockId) external view returns (bytes32) {\n return roots[_blockId];\n }\n\n /// @param _blockId consensus ID\n /// @return timestamp for provided consensus ID\n function getBlockTimestamp(uint32 _blockId) external view returns (uint32) {\n return roots[_blockId] == bytes32(0) ? 0 : _blockId;\n }\n\n /// @dev batch getter for FCDs\n /// @param _keys FCDs keys to fetch\n /// @return values array of FCDs values\n /// @return timestamps array of FCDs timestamps\n function getCurrentValues(bytes32[] calldata _keys)\n external\n view\n returns (uint256[] memory values, uint32[] memory timestamps)\n {\n timestamps = new uint32[](_keys.length);\n values = new uint256[](_keys.length);\n\n for (uint i=0; i<_keys.length;) {\n FirstClassData storage numericFCD = fcds[_keys[i]];\n values[i] = uint256(numericFCD.value);\n timestamps[i] = numericFCD.dataTimestamp;\n\n unchecked {\n // we can uncheck because `i` will not overflow in a lifetime\n i++;\n }\n }\n }\n\n /// @dev getter for single FCD value\n /// @param _key FCD key\n /// @return value FCD value\n /// @return timestamp FCD timestamp\n function getCurrentValue(bytes32 _key) external view returns (uint256 value, uint256 timestamp) {\n FirstClassData storage numericFCD = fcds[_key];\n return (uint256(numericFCD.value), numericFCD.dataTimestamp);\n }\n\n /// @dev getter for single FCD value in case its type is `int`\n /// @param _key FCD key\n /// @return value FCD value\n /// @return timestamp FCD timestamp\n function getCurrentIntValue(bytes32 _key) external view returns (int256 value, uint256 timestamp) {\n FirstClassData storage numericFCD = fcds[_key];\n return (numericFCD.value.toInt(), numericFCD.dataTimestamp);\n }\n\n function _setPadding(uint32 _padding) internal onlyOwner {\n if (_consensusData.padding == _padding) revert NoChangeToState();\n\n _consensusData.padding = _padding;\n emit LogPadding(msg.sender, _padding);\n }\n\n /// @dev we cloning last block time, because we will need reference point for next submissions\n function _cloneLastDataFromPrevChain(address _prevChain) internal {\n (bool success, bytes memory v) = _prevChain.staticcall(abi.encode(_VERSION_SELECTOR));\n uint256 prevVersion = success ? abi.decode(v, (uint256)) : 1;\n\n if (prevVersion == 1) {\n uint32 latestId = IBaseChainV1(address(_prevChain)).getLatestBlockId();\n _consensusData.lastTimestamp = IBaseChainV1(address(_prevChain)).getBlockTimestamp(latestId);\n\n // +1 because getLatestBlockId subtracts 1\n // +1 because it might be situation when tx is already in progress in old contract\n // and old contract do not have deprecated flag\n _consensusData.sequence = latestId + 2;\n _consensusData.blocksCountOffset = latestId + 2;\n } else { // VERSION 2\n // with new Registry, we have register/unregister methods\n // Chain will be deprecated, so there is no need to do \"+1\" as in old version\n // TODO what with current Registries??\n // we need a way to make it deprecated!\n ConsensusData memory data = BaseChain(_prevChain).getConsensusData();\n\n _consensusData.sequence = data.sequence;\n _consensusData.blocksCountOffset = data.sequence;\n _consensusData.lastTimestamp = data.lastTimestamp;\n }\n }\n}\n" + }, + "contracts/Chain.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./BaseChain.sol\";\n\ncontract Chain is BaseChain {\n IStakingBank public immutable stakingBank;\n\n event LogMint(address indexed minter, uint256 blockId, uint256 staked, uint256 power);\n event LogVoter(uint256 indexed blockId, address indexed voter, uint256 vote);\n\n error NotEnoughSignatures();\n error SignaturesOutOfOrder();\n\n /// @param _contractRegistry Registry address\n /// @param _padding required \"space\" between blocks in seconds\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n /// @param _allowForMixedType we have two \"types\" of Chain: HomeChain and ForeignChain, when we redeploying\n /// we don't want to mix up them, so we checking, if new Chain has the same type as current one.\n /// However, when we will be switching from one homechain to another one, we have to allow for this mixing up.\n /// This flag will tell contract, if this is the case.\n constructor(\n IRegistry _contractRegistry,\n uint32 _padding,\n uint16 _requiredSignatures,\n bool _allowForMixedType\n ) BaseChain(_contractRegistry, _padding, _requiredSignatures, _allowForMixedType) {\n stakingBank = IStakingBank(_contractRegistry.requireAndGetAddress(\"StakingBank\"));\n }\n\n /// @dev method for submitting consensus data\n /// @param _dataTimestamp consensus timestamp, this is time for all data in merkle tree including FCDs\n /// @param _root merkle root\n /// @param _keys FCDs keys\n /// @param _values FCDs values\n /// @param _v array of `v` part of validators signatures\n /// @param _r array of `r` part of validators signatures\n /// @param _s array of `s` part of validators signatures\n // solhint-disable-next-line function-max-lines, code-complexity\n function submit(\n uint32 _dataTimestamp,\n bytes32 _root,\n bytes32[] memory _keys,\n uint256[] memory _values,\n uint8[] memory _v,\n bytes32[] memory _r,\n bytes32[] memory _s\n ) external {\n // below two checks are only for pretty errors, so we can safe gas and allow for raw revert\n // if (_keys.length != _values.length) revert ArraysDataDoNotMatch();\n // if (_v.length != _r.length || _r.length != _s.length) revert ArraysDataDoNotMatch();\n\n _verifySubmitTimestampAndIncSequence(_dataTimestamp);\n\n // we can't expect minter will have exactly the same timestamp\n // but for sure we can demand not to be off by a lot, that's why +3sec\n // temporary remove this condition, because recently on ropsten we see cases when minter/node\n // can be even 100sec behind\n // require(_dataTimestamp <= block.timestamp + 3,\n // string(abi.encodePacked(\"oh, so you can predict the future:\", _dataTimestamp - block.timestamp + 48)));\n\n bytes memory testimony = abi.encodePacked(_dataTimestamp, _root);\n\n for (uint256 i = 0; i < _keys.length;) {\n if (uint224(_values[i]) != _values[i]) revert FCDOverflow();\n\n fcds[_keys[i]] = FirstClassData(uint224(_values[i]), _dataTimestamp);\n testimony = abi.encodePacked(testimony, _keys[i], _values[i]);\n\n unchecked {\n // we can't pass enough data to overflow\n i++;\n }\n }\n\n uint256 signatures = 0;\n uint256 power = 0;\n //uint256 staked = stakingBank.totalSupply();\n bytes32 affidavit = keccak256(testimony);\n\n address prevSigner = address(0x0);\n\n for (uint256 i; i < _v.length;) {\n address signer = recoverSigner(affidavit, _v[i], _r[i], _s[i]);\n uint256 balance = stakingBank.balanceOf(signer);\n\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\n\n prevSigner = signer;\n\n if (balance == 0) {\n unchecked { i++; }\n continue;\n }\n\n signatures++;\n emit LogVoter(uint256(_dataTimestamp), signer, balance);\n\n unchecked {\n // we can't overflow because that means token overflowed\n // and even if we do, we will get lower power\n power += balance;\n i++;\n }\n }\n\n if (signatures < _REQUIRED_SIGNATURES) revert NotEnoughSignatures();\n\n emit LogMint(msg.sender, _dataTimestamp, stakingBank.totalSupply(), power);\n\n // TODO remember to protect against flash loans when DPoS will be in place\n // we turn on power once we have DPoS in action, we have PoA now\n // require(power * 100 / staked >= 66, \"not enough power was gathered\");\n\n roots[_dataTimestamp] = _root;\n _consensusData.lastTimestamp = _dataTimestamp;\n }\n\n /// @inheritdoc BaseChain\n function isForeign() external pure virtual override returns (bool) {\n return false;\n }\n\n /// @dev helper method that returns all important data about current state of contract\n /// @return blockNumber `block.number`\n /// @return timePadding `this.padding`\n /// @return lastDataTimestamp timestamp for last submitted consensus\n /// @return lastId ID of last submitted consensus\n /// @return nextLeader leader for `block.timestamp + 1`\n /// @return nextBlockId block ID for `block.timestamp + padding`\n /// @return validators array of all validators addresses\n /// @return powers array of all validators powers\n /// @return locations array of all validators locations\n /// @return staked total UMB staked by validators\n /// @return minSignatures `this.requiredSignatures`\n function getStatus() external view virtual returns(\n uint256 blockNumber,\n uint32 timePadding,\n uint32 lastDataTimestamp,\n uint32 lastId,\n address nextLeader,\n uint32 nextBlockId,\n address[] memory validators,\n uint256[] memory powers,\n string[] memory locations,\n uint256 staked,\n uint16 minSignatures\n ) {\n ConsensusData memory data = _consensusData;\n\n blockNumber = block.number;\n timePadding = data.padding;\n lastId = data.lastTimestamp;\n lastDataTimestamp = lastId;\n minSignatures = _REQUIRED_SIGNATURES;\n\n staked = stakingBank.totalSupply();\n uint256 numberOfValidators = stakingBank.getNumberOfValidators();\n powers = new uint256[](numberOfValidators);\n validators = new address[](numberOfValidators);\n locations = new string[](numberOfValidators);\n\n for (uint256 i = 0; i < numberOfValidators;) {\n validators[i] = stakingBank.addresses(i);\n (, locations[i]) = stakingBank.validators(validators[i]);\n powers[i] = stakingBank.balanceOf(validators[i]);\n\n unchecked {\n // we will run out of gas before overflow happen\n i++;\n }\n }\n\n unchecked {\n // we will not overflow with timestamp in a lifetime\n nextBlockId = lastId + data.padding + 1;\n\n nextLeader = numberOfValidators > 0\n // we will not overflow with timestamp in a lifetime\n ? validators[getLeaderIndex(numberOfValidators, block.timestamp + 1)]\n : address(0);\n }\n }\n\n /// @return address of leader for next second\n function getNextLeaderAddress() external view returns (address) {\n return getLeaderAddressAtTime(block.timestamp + 1);\n }\n\n /// @return address of current leader\n function getLeaderAddress() external view returns (address) {\n return getLeaderAddressAtTime(block.timestamp);\n }\n\n /// @param _numberOfValidators total number of validators\n /// @param _timestamp timestamp for which you want to calculate index\n /// @return leader index, use it for StakingBank.addresses[index] to fetch leader address\n function getLeaderIndex(uint256 _numberOfValidators, uint256 _timestamp) public view virtual returns (uint256) {\n ConsensusData memory data = _consensusData;\n\n unchecked {\n // we will not overflow on `timestamp` and `padding` in a life time\n // timePadding + 1 => because padding is a space between blocks,\n // so next round starts on first block after padding\n // TODO will it work for off-chain??\n uint256 validatorIndex = data.sequence + (_timestamp - data.lastTimestamp) / (data.padding + 1);\n\n return validatorIndex % _numberOfValidators;\n }\n }\n\n // @todo - properly handled non-enabled validators, newly added validators, and validators with low stake\n /// @param _timestamp timestamp for which you want to calculate leader address\n /// @return leader address for provider timestamp\n function getLeaderAddressAtTime(uint256 _timestamp) public view virtual returns (address) {\n uint256 numberOfValidators = stakingBank.getNumberOfValidators();\n\n if (numberOfValidators == 0) {\n return address(0x0);\n }\n\n uint256 validatorIndex = getLeaderIndex(numberOfValidators, _timestamp);\n\n return stakingBank.addresses(validatorIndex);\n }\n\n /// @dev we had stack too deep in `submit` so this method was created as a solution\n // we increasing `_consensusData.sequence` here so we don't have to read sequence again in other place\n function _verifySubmitTimestampAndIncSequence(uint256 _dataTimestamp) internal {\n ConsensusData memory data = _consensusData;\n\n // `data.lastTimestamp` must be setup either on deployment\n // or via cloning from previous contract\n if (data.lastTimestamp == 0) revert ContractNotReady();\n\n unchecked {\n // we will not overflow with timestamp and padding in a life time\n if (data.lastTimestamp + data.padding >= _dataTimestamp) revert BlockSubmittedToFastOrDataToOld();\n }\n\n unchecked {\n // we will not overflow in a life time\n _consensusData.sequence = uint32(data.sequence + 1);\n }\n }\n}\n" + }, + "contracts/extensions/Registrable.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\n/// @dev Any contract that we want to register in ContractRegistry, must inherit from Registrable\nabstract contract Registrable {\n IRegistry public immutable contractRegistry;\n\n modifier onlyFromContract(address _msgSender, bytes32 _contractName) {\n require(\n contractRegistry.getAddress(_contractName) == _msgSender,\n string(abi.encodePacked(\"caller is not \", _contractName))\n );\n _;\n }\n\n modifier withRegistrySetUp() {\n require(address(contractRegistry) != address(0x0), \"_registry is empty\");\n _;\n }\n\n constructor(IRegistry _contractRegistry) {\n require(address(_contractRegistry) != address(0x0), \"_registry is empty\");\n contractRegistry = _contractRegistry;\n }\n\n /// @dev this method will be called as a first method in registration process when old contract will be replaced\n /// when called, old contract address is still in registry\n function register() virtual external;\n\n /// @dev this method will be called as a last method in registration process when old contract will be replaced\n /// when called, new contract address is already in registry\n function unregister() virtual external;\n\n /// @return contract name as bytes32\n function getName() virtual external pure returns (bytes32);\n\n /// @dev helper method for fetching StakingBank address\n function stakingBankContract() public view returns (IStakingBank) {\n return IStakingBank(contractRegistry.requireAndGetAddress(\"StakingBank\"));\n }\n\n /// @dev helper method for fetching UMB address\n function tokenContract() public view withRegistrySetUp returns (ERC20) {\n return ERC20(contractRegistry.requireAndGetAddress(\"UMB\"));\n }\n}\n" + }, + "contracts/ForeignChain.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./Chain.sol\";\n\n/// @dev contract for foreign chains\ncontract ForeignChain is Chain {\n error NotSupported();\n\n /// @param _contractRegistry Registry address\n /// @param _padding required \"space\" between blocks in seconds\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n constructor(\n IRegistry _contractRegistry,\n uint32 _padding,\n uint16 _requiredSignatures,\n bool _allowForMixedType\n ) Chain(_contractRegistry, _padding, _requiredSignatures, _allowForMixedType) {\n // no additional configuration needed\n }\n\n /// @inheritdoc BaseChain\n function isForeign() external pure override returns (bool) {\n return true;\n }\n\n /// @inheritdoc Chain\n /// @notice this method is made to be compatible with MasterChain, but it does not return full data eg validators\n /// data will be missing.\n /// @return blockNumber `block.number`\n /// @return timePadding `this.padding`\n /// @return lastDataTimestamp timestamp for last submitted consensus\n /// @return lastId ID of last submitted consensus\n /// @return nextLeader will be always address(0)\n /// @return nextBlockId block ID for `block.timestamp + padding`\n /// @return validators array will be always empty\n /// @return powers array will be always empty\n /// @return locations array will be always empty\n /// @return staked total UMB staked by validators\n /// @return minSignatures `this.requiredSignatures`\n function getStatus() external view override returns(\n uint256 blockNumber,\n uint32 timePadding,\n uint32 lastDataTimestamp,\n uint32 lastId,\n address nextLeader,\n uint32 nextBlockId,\n address[] memory validators,\n uint256[] memory powers,\n string[] memory locations,\n uint256 staked,\n uint16 minSignatures\n ) {\n ConsensusData memory data = _consensusData;\n\n blockNumber = block.number;\n timePadding = data.padding;\n lastId = data.lastTimestamp;\n lastDataTimestamp = lastId;\n minSignatures = _REQUIRED_SIGNATURES;\n\n staked = stakingBank.totalSupply();\n uint256 numberOfValidators = 0;\n powers = new uint256[](numberOfValidators);\n validators = new address[](numberOfValidators);\n locations = new string[](numberOfValidators);\n nextLeader = address(0);\n\n unchecked {\n // we will not overflow with timestamp in a lifetime\n nextBlockId = lastId + data.padding + 1;\n }\n }\n\n function getLeaderIndex(uint256, uint256) public pure override returns (uint256) {\n revert NotSupported();\n }\n\n function getLeaderAddressAtTime(uint256) public pure override returns (address) {\n revert NotSupported();\n }\n}\n" + }, + "contracts/interfaces/IBaseChainV1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IBaseChainV1 {\n /// @dev number of blocks (consensus rounds) saved in this contract\n function blocksCount() external returns (uint32);\n\n /// @dev number of all blocks that were generated before switching to this contract\n /// please note, that there might be a gap of one block when we switching from old to new contract\n /// see constructor for details\n function blocksCountOffset() external returns (uint32);\n\n function getLatestBlockId() external view returns (uint32);\n\n function getBlockTimestamp(uint32 _blockId) external view returns (uint32);\n\n function getStatus() external view returns (\n uint256 blockNumber,\n uint16 timePadding,\n uint32 lastDataTimestamp,\n uint32 lastId,\n uint32 nextBlockId\n );\n}\n" + }, + "contracts/interfaces/IRegistry.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\n\ninterface IRegistry {\n event LogRegistered(address indexed destination, bytes32 name);\n\n /// @dev imports new contract addresses and override old addresses, if they exist under provided name\n /// This method can be used for contracts that for some reason do not have `getName` method\n /// @param _names array of contract names that we want to register\n /// @param _destinations array of contract addresses\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external;\n\n /// @dev imports new contracts and override old addresses, if they exist.\n /// Names of contracts are fetched directly from each contract by calling `getName`\n /// @param _destinations array of contract addresses\n function importContracts(address[] calldata _destinations) external;\n\n /// @dev this method ensure, that old and new contract is aware of it state in registry\n /// Note: BSC registry does not have this method. This method was introduced in later stage.\n /// @param _newContract address of contract that will replace old one\n function atomicUpdate(address _newContract) external;\n\n /// @dev similar to `getAddress` but throws when contract name not exists\n /// @param name contract name\n /// @return contract address registered under provided name or throws, if does not exists\n function requireAndGetAddress(bytes32 name) external view returns (address);\n\n /// @param name contract name in a form of bytes32\n /// @return contract address registered under provided name\n function getAddress(bytes32 name) external view returns (address);\n\n /// @param _name contract name\n /// @return contract address assigned to the name or address(0) if not exists\n function getAddressByString(string memory _name) external view returns (address);\n\n /// @dev helper method that converts string to bytes32,\n /// you can use to to generate contract name\n function stringToBytes32(string memory _string) external pure returns (bytes32 result);\n}\n" + }, + "contracts/interfaces/IStakingBank.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IStakingBank is IERC20 {\n /// @param id address of validator wallet\n /// @param location URL of the validator API\n struct Validator {\n address id;\n string location;\n }\n\n event LogValidatorRegistered(address indexed id);\n event LogValidatorUpdated(address indexed id);\n event LogValidatorRemoved(address indexed id);\n event LogMinAmountForStake(uint256 minAmountForStake);\n\n /// @dev setter for `minAmountForStake`\n function setMinAmountForStake(uint256 _minAmountForStake) external;\n\n /// @dev allows to stake `token` by validators\n /// Validator needs to approve StakingBank beforehand\n /// @param _value amount of tokens to stake\n function stake(uint256 _value) external;\n\n /// @dev notification about approval from `_from` address on UMB token\n /// Staking bank will stake max approved amount from `_from` address\n /// @param _from address which approved token spend for IStakingBank\n function receiveApproval(address _from) external returns (bool success);\n\n /// @dev withdraws stake tokens\n /// it throws, when balance will be less than required minimum for stake\n /// to withdraw all use `exit`\n function withdraw(uint256 _value) external returns (bool success);\n\n /// @dev unstake and withdraw all tokens\n function exit() external returns (bool success);\n\n /// @dev creates (register) new validator\n /// @param _id validator address\n /// @param _location location URL of the validator API\n function create(address _id, string calldata _location) external;\n\n /// @dev removes validator\n /// @param _id validator wallet\n function remove(address _id) external;\n\n /// @dev updates validator location\n /// @param _id validator wallet\n /// @param _location new validator URL\n function update(address _id, string calldata _location) external;\n\n /// @return total number of registered validators (with and without balance)\n function getNumberOfValidators() external view returns (uint256);\n\n /// @dev gets validator address for provided index\n /// @param _ix index in array of list of all validators wallets\n function addresses(uint256 _ix) external view returns (address);\n\n /// @param _id address of validator\n /// @return id address of validator\n /// @return location URL of validator\n function validators(address _id) external view returns (address id, string memory location);\n}\n" + }, + "contracts/interfaces/IStakingBankStatic.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./IStakingBank.sol\";\n\n\ninterface IStakingBankStatic is IStakingBank {\n /// @param _validators array of validators addresses to verify\n /// @return TRUE when all validators are valid, FALSE otherwise\n function verifyValidators(address[] calldata _validators) external view returns (bool);\n}\n" + }, + "contracts/interfaces/IUmbrellaFeeds.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IUmbrellaFeeds {\n struct PriceData {\n /// @dev this is placeholder, that can be used for some additional data\n /// atm of creating this smart contract, it is only used as marker for removed data (when == type(uint8).max)\n uint8 data;\n /// @dev heartbeat: how often price data will be refreshed in case price stay flat\n uint24 heartbeat;\n /// @dev timestamp: price time, at this time validators run consensus\n uint32 timestamp;\n /// @dev price\n uint128 price;\n }\n\n struct Signature {\n uint8 v;\n bytes32 r;\n bytes32 s;\n }\n\n /// @dev method for submitting consensus data\n /// @param _priceKeys array of keys for `_priceDatas`\n /// @param _priceDatas PriceData signed by validators\n /// @param _signatures validators signatures\n function update(\n bytes32[] calldata _priceKeys,\n PriceData[] calldata _priceDatas,\n Signature[] calldata _signatures\n ) external;\n\n /// @dev it will return array of price datas for provided `_keys`\n /// In case ony of feed does not exist, fallback call will be executed for that feed.\n /// @notice If data for any key not exists, function will revert. Use `getManyPriceDataRaw` method if you don't\n /// want revert.\n /// @param _keys array of feed keys\n /// @return data PriceData array\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data);\n\n /// @dev same as getManyPriceData() but does not revert on empty data.\n /// @notice This method does no revert if some data does not exists.\n /// Check `data.timestamp` to see if price exist, if it is 0, then it does not exist.\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data);\n\n /// @dev this is main endpoint for reading feeds.\n /// In case timestamp is empty (that means there is no data), contract will revert.\n /// If you do not need whole data from `PriceData` struct, you can save some gas by using other view methods that\n /// returns just what you need.\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return data full PriceData struct\n function getPriceData(bytes32 _key) external view returns (PriceData memory data);\n\n /// @notice reader for mapping\n /// @param _key hash of feed name\n /// @return data full PriceData struct\n function prices(bytes32 _key) external view returns (PriceData memory data);\n\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return price\n function getPrice(bytes32 _key) external view returns (uint128 price);\n\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return price\n /// @return timestamp\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp);\n\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return price\n /// @return timestamp\n /// @return heartbeat\n function getPriceTimestampHeartbeat(bytes32 _key)\n external\n view\n returns (uint128 price, uint32 timestamp, uint24 heartbeat);\n\n /// @dev This method should be used only for Layer2 as it is more gas consuming than others views.\n /// @notice It does not revert on empty data.\n /// @param _name string feed name\n /// @return data PriceData\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data);\n\n /// @dev decimals for prices stored in this contract\n function DECIMALS() external view returns (uint8); // solhint-disable-line func-name-mixedcase\n}\n" + }, + "contracts/interfaces/StakingBankStaticNotSupported.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./IStakingBank.sol\";\n\nabstract contract StakingBankStaticNotSupported is IStakingBank {\n error NotSupported();\n\n function create(address, string calldata) external pure {\n revert NotSupported();\n }\n\n function update(address, string calldata) external pure {\n revert NotSupported();\n }\n\n function remove(address) external pure {\n revert NotSupported();\n }\n\n function transfer(address, uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function transferFrom(address, address, uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function receiveApproval(address) external pure returns (bool) {\n revert NotSupported();\n }\n\n function allowance(address, address) external pure returns (uint256) {\n revert NotSupported();\n }\n\n function approve(address, uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function stake(uint256) external pure {\n revert NotSupported();\n }\n\n function withdraw(uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function exit() external pure returns (bool) {\n revert NotSupported();\n }\n\n function setMinAmountForStake(uint256) external pure {\n revert NotSupported();\n }\n}\n" + }, + "contracts/mock/Distributor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport \"../Registry.sol\";\n\ncontract Distributor is Ownable {\n address[] public recipients;\n uint256 public bottomLimit = 5e17;\n uint256 public topLimit = 1e18;\n\n constructor(address[] memory _recipients) {\n recipients = _recipients;\n }\n\n receive() external payable {\n distribute();\n }\n\n function setLimits(uint256 _bottom, uint256 _top) external onlyOwner {\n bottomLimit = _bottom;\n topLimit = _top;\n }\n\n function withdraw() external {\n uint balance = address(this).balance;\n uint buffer = recipients.length * (topLimit - bottomLimit);\n\n if (balance > buffer) {\n payable(owner()).transfer(balance - buffer);\n }\n }\n\n function addRecipients(address[] calldata _recipients) external onlyOwner {\n for (uint256 i = 0; i < _recipients.length; i++) {\n recipients.push(_recipients[i]);\n }\n }\n\n function removeRecipient(address _recipient) external onlyOwner {\n for (uint256 i = 0; i < recipients.length; i++) {\n if (recipients[i] == _recipient) {\n recipients[i] = recipients[recipients.length - 1];\n recipients.pop();\n return;\n }\n }\n }\n\n function recipientsCount() external view returns (uint256) {\n return recipients.length;\n }\n\n function allRecipients() external view returns (address[] memory) {\n return recipients;\n }\n\n function getName() external pure returns (bytes32) {\n return \"Distributor\";\n }\n\n function distribute() public {\n uint256 limit = bottomLimit;\n uint256 top = topLimit;\n uint256 count = recipients.length;\n uint256 totalBalance = address(this).balance;\n\n for (uint256 i = 0; i < count; i++) {\n uint256 balance = recipients[i].balance;\n\n if (balance > limit) {\n continue;\n }\n\n uint256 amount = top - balance > totalBalance ? totalBalance : top - balance;\n\n if (amount > 0) {\n payable(recipients[i]).transfer(amount);\n totalBalance -= amount;\n }\n }\n }\n}\n" + }, + "contracts/mock/LimitedMintingToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\ncontract LimitedMintingToken is ERC20, Ownable {\n struct MintData {\n uint256 dailyAllowance;\n mapping (address => uint256) lastMintTimestamp;\n mapping (address => uint256) todaysMintedAmount;\n }\n\n MintData public mintData;\n\n constructor(string memory _name, string memory _symbol, uint256 _dailyAllowance) ERC20(_name, _symbol) {\n mintData.dailyAllowance = _dailyAllowance;\n }\n\n function mint(address _holder, uint256 _amount) external {\n MintData storage data = mintData;\n\n (uint256 limit, bool fullLimit) = _currentLimit(data);\n\n require(limit > 0, \"This address already claimed the maximum daily amount\");\n\n uint256 lastTimestamp = data.lastMintTimestamp[msg.sender];\n uint256 mintedAmount = data.todaysMintedAmount[msg.sender];\n\n uint256 amount = _amount > limit ? limit : _amount;\n data.lastMintTimestamp[msg.sender] = fullLimit ? block.timestamp : lastTimestamp;\n data.todaysMintedAmount[msg.sender] = fullLimit ? amount : mintedAmount + amount;\n\n _mint(_holder, amount);\n }\n\n function mintApproveAndStake(IStakingBank _stakingBank, address _holder, uint256 _amount) external {\n _mint(_holder, _amount);\n _approve(_holder, address(_stakingBank), _amount);\n _stakingBank.receiveApproval(_holder);\n }\n\n function getDailyAllowance() external view returns (uint256) {\n return mintData.dailyAllowance;\n }\n\n function getName() external pure returns (bytes32) {\n return \"UMB\";\n }\n\n function setDailyAllowance(uint256 newDailyAllowance) public onlyOwner {\n MintData storage data = mintData;\n data.dailyAllowance = newDailyAllowance;\n }\n\n function _currentLimit(MintData storage data) internal view returns (uint256 limit, bool fullLimit) {\n uint256 lastMint = data.lastMintTimestamp[msg.sender];\n fullLimit = block.timestamp - lastMint >= 24 hours;\n\n uint256 usedLimit = data.todaysMintedAmount[msg.sender];\n\n limit = fullLimit ? data.dailyAllowance : data.dailyAllowance - usedLimit;\n }\n}\n" + }, + "contracts/mock/Token.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\n// please remember this is our dummy token!\n// it will be replaced by proper DPoS solution in future\ncontract Token is ERC20 {\n constructor(\n string memory _name,\n string memory _symbol) ERC20(_name, _symbol) {\n }\n\n function mint(address _holder, uint256 _amount) external {\n _mint(_holder, _amount);\n }\n\n function mintApproveAndStake(IStakingBank _stakingBank, address _holder, uint256 _amount) external {\n _mint(_holder, _amount);\n _approve(_holder, address(_stakingBank), _amount);\n _stakingBank.receiveApproval(_holder);\n }\n\n function getName() external pure returns (bytes32) {\n return \"UMB\";\n }\n}\n" + }, + "contracts/onChainFeeds/UmbrellaFeeds.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/IUmbrellaFeeds.sol\";\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IStakingBankStatic.sol\";\n\n/// @dev Main contract for all on-chain data.\n/// Check `UmbrellaFeedsReader` to see how to integrate.\n///\n/// @notice This contract can be destroyed and replaced with new one (with new address).\n/// For best gas efficiency you should pick one of two ways of integration:\n/// 1. make `UmbrellaFeeds` immutable and use fallback in case of selfdestruct. After new deployment, it is recommended\n/// to update address to avoid fallback and reduce gas cost to minimum. In long run this is most efficient solution,\n/// better than any proxy.\n/// 2. always check newest `UmbrellaFeeds` via `Regostry` and fallback will not be needed.\ncontract UmbrellaFeeds is IUmbrellaFeeds {\n bytes constant public ETH_PREFIX = \"\\x19Ethereum Signed Message:\\n32\";\n string constant public NAME = \"UmbrellaFeeds\";\n\n /// @dev deployment time, used for protect for unintentional destroy\n uint256 public immutable DEPLOYED_AT; // solhint-disable-line var-name-mixedcase\n\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\n /// resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev StakingBank contract where list of validators is stored\n IStakingBankStatic public immutable STAKING_BANK; // solhint-disable-line var-name-mixedcase\n\n /// @dev minimal number of signatures required for accepting price submission (PoA)\n uint16 public immutable REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\n\n /// @dev decimals for prices stored in this contract\n uint8 public immutable DECIMALS; // solhint-disable-line var-name-mixedcase\n\n /// @notice map of all prices stored in this contract, key for map is hash of feed name\n /// eg for \"ETH-USD\" feed, key will be hash(\"ETH-USD\")\n mapping (bytes32 => PriceData) private _prices;\n\n error ArraysDataDoNotMatch();\n error FeedNotExist();\n error NotEnoughSignatures();\n error InvalidSigner();\n error InvalidRequiredSignatures();\n error SignaturesOutOfOrder();\n error ECDSAInvalidSignatureS();\n error ECDSAInvalidSignatureV();\n error OldData();\n error ContractInUse();\n error ContractNotInitialised();\n\n /// @param _contractRegistry Registry address\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n /// @param _decimals decimals for prices stored in this contract\n constructor(\n IRegistry _contractRegistry,\n uint16 _requiredSignatures,\n uint8 _decimals\n ) {\n if (_requiredSignatures == 0) revert InvalidRequiredSignatures();\n\n REGISTRY = _contractRegistry;\n REQUIRED_SIGNATURES = _requiredSignatures;\n STAKING_BANK = IStakingBankStatic(_contractRegistry.requireAndGetAddress(\"StakingBank\"));\n DECIMALS = _decimals;\n DEPLOYED_AT = block.timestamp;\n }\n\n /// @dev destroys old contract\n /// there is sanity check that prevents abuse of destroy method\n /// @param _name string feed key to verify, that contract was initialised\n function destroy(string calldata _name) external {\n if (REGISTRY.getAddressByString(NAME) == address(this)) revert ContractInUse();\n\n if (_prices[keccak256(abi.encodePacked(_name))].timestamp == 0 && DEPLOYED_AT + 3 days > block.timestamp) {\n revert ContractNotInitialised();\n }\n\n selfdestruct(payable(msg.sender));\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function update(\n bytes32[] calldata _priceKeys,\n PriceData[] calldata _priceDatas,\n Signature[] calldata _signatures\n ) external {\n if (_priceKeys.length != _priceDatas.length) revert ArraysDataDoNotMatch();\n\n bytes32 priceDataHash = keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n verifySignatures(priceDataHash, _signatures);\n\n uint256 i;\n\n while (i < _priceDatas.length) {\n bytes32 priceKey = _priceKeys[i];\n\n // we do not allow for older prices\n // at the same time it prevents from reusing signatures\n if (_prices[priceKey].timestamp >= _priceDatas[i].timestamp) revert OldData();\n\n _prices[priceKey] = _priceDatas[i];\n\n // atm there is no need for events, so in order to save gas, we do not emit any\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n if (data[i].timestamp == 0) revert FeedNotExist();\n\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function prices(bytes32 _key) external view returns (PriceData memory data) {\n data = _prices[_key];\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceData(bytes32 _key) external view returns (PriceData memory data) {\n data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPrice(bytes32 _key) external view returns (uint128 price) {\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return data.price;\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp) {\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp);\n }\n\n function getPriceTimestampHeartbeat(bytes32 _key)\n external\n view\n returns (uint128 price, uint32 timestamp, uint24 heartbeat)\n {\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp, data.heartbeat);\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data) {\n bytes32 key = keccak256(abi.encodePacked(_name));\n data = _prices[key];\n }\n\n /// @dev helper method for QA purposes\n /// @return hash of data that are signed by validators (keys and priced data)\n function hashData(bytes32[] calldata _priceKeys, PriceData[] calldata _priceDatas)\n external\n view\n returns (bytes32)\n {\n return keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n }\n\n /// @param _hash hash of signed data\n /// @param _signatures array of validators signatures\n function verifySignatures(bytes32 _hash, Signature[] calldata _signatures) public view {\n address prevSigner = address(0x0);\n\n if (_signatures.length < REQUIRED_SIGNATURES) revert NotEnoughSignatures();\n\n address[] memory validators = new address[](REQUIRED_SIGNATURES);\n\n // to save gas we check only required number of signatures\n // case, where you can have part of signatures invalid but still enough valid in total is not supported\n for (uint256 i; i < REQUIRED_SIGNATURES;) {\n (uint8 v, bytes32 r, bytes32 s) = (_signatures[i].v, _signatures[i].r, _signatures[i].s);\n\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n revert ECDSAInvalidSignatureS();\n }\n\n if (uint8(v) != 27 && uint8(v) != 28) revert ECDSAInvalidSignatureV();\n\n address signer = recoverSigner(_hash, v, r, s);\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\n\n // because we check only required number of signatures, any invalid one will cause revert\n prevSigner = signer;\n validators[i] = signer;\n\n unchecked { i++; }\n }\n\n // bulk verification can optimise gas when we have 5 or more validators\n if (!STAKING_BANK.verifyValidators(validators)) revert InvalidSigner();\n }\n\n function getChainId() public view returns (uint256 id) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n id := chainid()\n }\n }\n\n /// @param _hash hashed of data\n /// @param _v part of signature\n /// @param _r part of signature\n /// @param _s part of signature\n /// @return signer address\n function recoverSigner(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _hash));\n return ecrecover(hash, _v, _r, _s);\n }\n\n /// @dev to follow Registrable interface\n function getName() public pure returns (bytes32) {\n return \"UmbrellaFeeds\";\n }\n}\n" + }, + "contracts/onChainFeeds/UmbrellaFeedsReader.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IUmbrellaFeeds.sol\";\n\n/// @dev This is optional price reader for just one feed.\n/// It comes with chanilink interface that makes migration process easier.\n/// For maximum gas optimisation it is recommended to use UmbrellaFeeds directly - simply follow this contract as\n/// a guide for integration.\n///\n/// This contract has build in fallback feature in case, `UmbrellaFeeds` will be replaced by newer contract.\n/// Fallback is transparent for the user, no additional setup is needed.\n///\n/// How fallback feature works? If data for provided key is empty (when UmbrellaFeeds was destroyed and replaced),\n/// contract will execute following procedure:\n/// 1. if data is empty, contract will check if there is new registered contract with requested data\n/// 2. if data is found in new contract it will be returned\n/// 3. if there is no data or there is no new contract tx will revert.\ncontract UmbrellaFeedsReader {\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\n /// resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev contract where all the feeds are stored\n address public immutable UMBRELLA_FEEDS; // solhint-disable-line var-name-mixedcase\n\n /// @dev key (hash of string key), under which feed is being stored\n bytes32 public immutable KEY; // solhint-disable-line var-name-mixedcase\n\n /// @dev string representation of feed key (feed name)\n string public description;\n\n /// @dev decimals for feed\n uint8 internal immutable _DECIMALS; // solhint-disable-line var-name-mixedcase\n\n error EmptyAddress();\n error FeedNotExist();\n\n /// @param _registry IRegistry address\n /// @param _umbrellaFeeds UmbrellaFeeds address\n /// @param _key price data key (before hashing)\n constructor(IRegistry _registry, IUmbrellaFeeds _umbrellaFeeds, string memory _key) {\n if (address(_registry) == address(0)) revert EmptyAddress();\n\n REGISTRY = _registry;\n UMBRELLA_FEEDS = address(_umbrellaFeeds);\n description = _key;\n _DECIMALS = _umbrellaFeeds.DECIMALS();\n\n bytes32 hash = keccak256(abi.encodePacked(_key));\n KEY = hash;\n\n // sanity check\n _umbrellaFeeds.getPriceData(hash);\n }\n\n /// @dev decimals for feed\n function decimals() external view returns (uint8) {\n return _DECIMALS;\n }\n\n /// @dev this method follows chainlink interface for easy migration, NOTE: not all returned data are covered!\n /// latestRoundData() raise exception when there is no data, instead of returning unset values,\n /// which could be misinterpreted as actual reported values.\n /// It DOES NOT raise when data is outdated (based on heartbeat and timestamp).\n /// @notice You can save some gas by doing call directly to `UMBRELLA_FEEDS` contract.\n /// @return uint80 originally `roundId`, not in use, always 0\n /// @return answer price\n /// @return uint256 originally `startedAt`, not in use, always 0\n /// @return updatedAt last timestamp data was updated\n /// @return uint80 originally `answeredInRound` not in use, always 0\n function latestRoundData()\n external\n view\n returns (\n uint80 /* roundId */,\n int256 answer,\n uint256 /* startedAt */,\n uint256 updatedAt,\n uint80 /* answeredInRound */\n )\n {\n IUmbrellaFeeds.PriceData memory priceData = _getPriceDataRaw();\n\n if (priceData.timestamp == 0) {\n priceData = _fallbackCall();\n }\n\n return (0, int256(uint256(priceData.price)), 0, priceData.timestamp, 0);\n }\n\n /// @dev this is main endpoint for reading feed. Feed is read from UmbrellaFeeds contract using hardcoded `KEY`.\n /// In case timestamp is empty (that means there is no data), contract will execute fallback call.\n /// @notice revert on empty data\n function getPriceData() external view returns (IUmbrellaFeeds.PriceData memory priceData) {\n priceData = _getPriceDataRaw();\n\n if (priceData.timestamp == 0) {\n priceData = _fallbackCall();\n }\n }\n\n /// @dev same as `getPriceData` but does not revert when no data\n function getPriceDataRaw() external view returns (IUmbrellaFeeds.PriceData memory priceData) {\n priceData = _getPriceDataRaw();\n\n if (priceData.timestamp == 0) {\n return _fallbackCallRaw();\n }\n }\n\n /// @dev same as `getPriceData` but does not revert when no data\n function _getPriceDataRaw() internal view returns (IUmbrellaFeeds.PriceData memory priceData) {\n (bool success, bytes memory data) = UMBRELLA_FEEDS.staticcall(\n abi.encodeWithSelector(IUmbrellaFeeds.prices.selector, KEY)\n );\n\n if (success && data.length != 0) {\n priceData = abi.decode(data, (IUmbrellaFeeds.PriceData));\n }\n }\n\n /// @dev it will revert on empty data\n function _fallbackCall() internal view returns (IUmbrellaFeeds.PriceData memory data) {\n address umbrellaFeeds = REGISTRY.getAddressByString(\"UmbrellaFeeds\");\n\n // if contract was NOT updated, fallback is not needed, data does not exist - revert\n if (umbrellaFeeds == UMBRELLA_FEEDS) revert FeedNotExist();\n\n data = IUmbrellaFeeds(umbrellaFeeds).getPriceData(KEY);\n }\n\n /// @dev it will not revert on empty data\n function _fallbackCallRaw() internal view returns (IUmbrellaFeeds.PriceData memory data) {\n address umbrellaFeeds = REGISTRY.getAddressByString(\"UmbrellaFeeds\");\n\n // if contract was updated, we do fallback\n if (umbrellaFeeds != UMBRELLA_FEEDS) {\n data = IUmbrellaFeeds(umbrellaFeeds).prices(KEY);\n }\n }\n}\n" + }, + "contracts/onChainFeeds/UmbrellaFeedsReaderFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\nimport \"./UmbrellaFeedsReader.sol\";\n\n/// @notice Factory to deploy UmbrellaFeedsReader contract\ncontract UmbrellaFeedsReaderFactory {\n /// @dev Registry contract where list of all addresses is stored. Used to resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev list of all readers\n mapping (bytes32 => UmbrellaFeedsReader) public readers;\n\n event NewUmbrellaFeedsReader(UmbrellaFeedsReader indexed umbrellaFeedsReader, string feedName);\n\n error EmptyAddress();\n\n constructor(IRegistry _registry) {\n if (address(_registry) == address(0)) revert EmptyAddress();\n\n REGISTRY = _registry;\n }\n\n /// @dev Method to deploy new UmbrellaFeedsReader for particular key.\n /// This deployment is optional and it can be done by anyone who needs it.\n /// Reader can be used to simplify migration from Chainlink to Umbrella.\n ///\n /// Check UmbrellaFeedsReader docs for more details.\n ///\n /// We not using minimal proxy because it does not allow for immutable variables.\n /// @param _feedName string Feed name that is registered in UmbrellaFeeds\n /// @return reader UmbrellaFeedsReader contract address, in case anyone wants to use it from Layer1\n function deploy(string memory _feedName) external returns (UmbrellaFeedsReader reader) {\n reader = deployed(_feedName);\n IUmbrellaFeeds umbrellaFeeds = IUmbrellaFeeds(REGISTRY.getAddressByString(\"UmbrellaFeeds\"));\n\n // if UmbrellaFeeds contract is up to date, there is no need to redeploy\n if (address(reader) != address(0) && address(reader.UMBRELLA_FEEDS()) == address(umbrellaFeeds)) {\n return reader;\n }\n\n reader = new UmbrellaFeedsReader(REGISTRY, umbrellaFeeds, _feedName);\n readers[hash(_feedName)] = reader;\n\n emit NewUmbrellaFeedsReader(reader, _feedName);\n }\n\n function deployed(string memory _feedName) public view returns (UmbrellaFeedsReader) {\n return readers[hash(_feedName)];\n }\n\n function hash(string memory _feedName) public pure returns (bytes32) {\n return keccak256(abi.encodePacked(_feedName));\n }\n\n /// @dev to follow Registrable interface\n function getName() public pure returns (bytes32) {\n return \"UmbrellaFeedsReaderFactory\";\n }\n}\n" + }, + "contracts/onChainFeeds/zk-link/UmbrellaFeeds.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../../interfaces/IUmbrellaFeeds.sol\";\nimport \"../../interfaces/IRegistry.sol\";\nimport \"../../interfaces/IStakingBankStatic.sol\";\n\n/// @dev Main contract for all on-chain data.\n/// Check `UmbrellaFeedsReader` to see how to integrate.\n///\n/// @notice This contract can be destroyed and replaced with new one (with new address).\n/// For best gas efficiency you should pick one of two ways of integration:\n/// 1. make `UmbrellaFeeds` immutable and use fallback in case of selfdestruct. After new deployment, it is recommended\n/// to update address to avoid fallback and reduce gas cost to minimum. In long run this is most efficient solution,\n/// better than any proxy.\n/// 2. always check newest `UmbrellaFeeds` via `Regostry` and fallback will not be needed.\ncontract UmbrellaFeeds is IUmbrellaFeeds {\n bytes constant public ETH_PREFIX = \"\\x19Ethereum Signed Message:\\n32\";\n string constant public NAME = \"UmbrellaFeeds\";\n\n /// @dev deployment time, used for protect for unintentional destroy\n uint256 public immutable DEPLOYED_AT; // solhint-disable-line var-name-mixedcase\n\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\n /// resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev StakingBank contract where list of validators is stored\n IStakingBankStatic public immutable STAKING_BANK; // solhint-disable-line var-name-mixedcase\n\n /// @dev minimal number of signatures required for accepting price submission (PoA)\n uint16 public immutable REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\n\n /// @dev decimals for prices stored in this contract\n uint8 public immutable DECIMALS; // solhint-disable-line var-name-mixedcase\n\n /// @dev in case selfdestruct is not supported, this flag will make sure contract is not usable anymore\n bool public disabled;\n\n /// @notice map of all prices stored in this contract, key for map is hash of feed name\n /// eg for \"ETH-USD\" feed, key will be hash(\"ETH-USD\")\n mapping (bytes32 => PriceData) private _prices;\n\n error SelfDestruct();\n error ArraysDataDoNotMatch();\n error FeedNotExist();\n error NotEnoughSignatures();\n error InvalidSigner();\n error InvalidRequiredSignatures();\n error SignaturesOutOfOrder();\n error ECDSAInvalidSignatureS();\n error ECDSAInvalidSignatureV();\n error OldData();\n error ContractInUse();\n error ContractNotInitialised();\n\n /// @param _contractRegistry Registry address\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n /// @param _decimals decimals for prices stored in this contract\n constructor(\n IRegistry _contractRegistry,\n uint16 _requiredSignatures,\n uint8 _decimals\n ) {\n if (_requiredSignatures == 0) revert InvalidRequiredSignatures();\n\n REGISTRY = _contractRegistry;\n REQUIRED_SIGNATURES = _requiredSignatures;\n STAKING_BANK = IStakingBankStatic(_contractRegistry.requireAndGetAddress(\"StakingBank\"));\n DECIMALS = _decimals;\n DEPLOYED_AT = block.timestamp;\n }\n\n /// @dev destroys old contract\n /// there is sanity check that prevents abuse of destroy method\n /// @param _name string feed key to verify, that contract was initialised\n function destroy(string calldata _name) external {\n if (REGISTRY.getAddressByString(NAME) == address(this)) revert ContractInUse();\n\n if (_prices[keccak256(abi.encodePacked(_name))].timestamp == 0 && DEPLOYED_AT + 3 days > block.timestamp) {\n revert ContractNotInitialised();\n }\n\n disabled = true;\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function update(\n bytes32[] calldata _priceKeys,\n PriceData[] calldata _priceDatas,\n Signature[] calldata _signatures\n ) external {\n if (disabled) revert SelfDestruct();\n if (_priceKeys.length != _priceDatas.length) revert ArraysDataDoNotMatch();\n\n bytes32 priceDataHash = keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n verifySignatures(priceDataHash, _signatures);\n\n uint256 i;\n\n while (i < _priceDatas.length) {\n bytes32 priceKey = _priceKeys[i];\n\n // we do not allow for older prices\n // at the same time it prevents from reusing signatures\n if (_prices[priceKey].timestamp >= _priceDatas[i].timestamp) revert OldData();\n\n _prices[priceKey] = _priceDatas[i];\n\n // atm there is no need for events, so in order to save gas, we do not emit any\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n if (disabled) revert SelfDestruct();\n\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n if (data[i].timestamp == 0) revert FeedNotExist();\n\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n if (disabled) revert SelfDestruct();\n\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function prices(bytes32 _key) external view returns (PriceData memory data) {\n if (disabled) revert SelfDestruct();\n\n data = _prices[_key];\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceData(bytes32 _key) external view returns (PriceData memory data) {\n if (disabled) revert SelfDestruct();\n\n data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPrice(bytes32 _key) external view returns (uint128 price) {\n if (disabled) revert SelfDestruct();\n\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return data.price;\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp) {\n if (disabled) revert SelfDestruct();\n\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp);\n }\n\n function getPriceTimestampHeartbeat(bytes32 _key)\n external\n view\n returns (uint128 price, uint32 timestamp, uint24 heartbeat)\n {\n if (disabled) revert SelfDestruct();\n\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp, data.heartbeat);\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data) {\n if (disabled) revert SelfDestruct();\n\n bytes32 key = keccak256(abi.encodePacked(_name));\n data = _prices[key];\n }\n\n /// @dev helper method for QA purposes\n /// @return hash of data that are signed by validators (keys and priced data)\n function hashData(bytes32[] calldata _priceKeys, PriceData[] calldata _priceDatas)\n external\n view\n returns (bytes32)\n {\n return keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n }\n\n /// @param _hash hash of signed data\n /// @param _signatures array of validators signatures\n function verifySignatures(bytes32 _hash, Signature[] calldata _signatures) public view {\n address prevSigner = address(0x0);\n\n if (_signatures.length < REQUIRED_SIGNATURES) revert NotEnoughSignatures();\n\n address[] memory validators = new address[](REQUIRED_SIGNATURES);\n\n // to save gas we check only required number of signatures\n // case, where you can have part of signatures invalid but still enough valid in total is not supported\n for (uint256 i; i < REQUIRED_SIGNATURES;) {\n (uint8 v, bytes32 r, bytes32 s) = (_signatures[i].v, _signatures[i].r, _signatures[i].s);\n\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n revert ECDSAInvalidSignatureS();\n }\n\n if (uint8(v) != 27 && uint8(v) != 28) revert ECDSAInvalidSignatureV();\n\n address signer = recoverSigner(_hash, v, r, s);\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\n\n // because we check only required number of signatures, any invalid one will cause revert\n prevSigner = signer;\n validators[i] = signer;\n\n unchecked { i++; }\n }\n\n // bulk verification can optimise gas when we have 5 or more validators\n if (!STAKING_BANK.verifyValidators(validators)) revert InvalidSigner();\n }\n\n function getChainId() public view returns (uint256 id) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n id := chainid()\n }\n }\n\n /// @param _hash hashed of data\n /// @param _v part of signature\n /// @param _r part of signature\n /// @param _s part of signature\n /// @return signer address\n function recoverSigner(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _hash));\n return ecrecover(hash, _v, _r, _s);\n }\n\n /// @dev to follow Registrable interface\n function getName() public pure returns (bytes32) {\n return \"UmbrellaFeeds\";\n }\n}\n" + }, + "contracts/Registry.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\n// Inheritance\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport \"./extensions/Registrable.sol\";\nimport \"./interfaces/IRegistry.sol\";\n\n/// @dev contracts registry\n/// protocol uses this registry to fetch current contract addresses\ncontract Registry is IRegistry, Ownable {\n /// name => contract address\n mapping(bytes32 => address) public registry;\n\n\n error NameNotRegistered();\n error ArraysDataDoNotMatch();\n\n /// @inheritdoc IRegistry\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external onlyOwner {\n if (_names.length != _destinations.length) revert ArraysDataDoNotMatch();\n\n for (uint i = 0; i < _names.length;) {\n registry[_names[i]] = _destinations[i];\n emit LogRegistered(_destinations[i], _names[i]);\n\n unchecked {\n i++;\n }\n }\n }\n\n /// @inheritdoc IRegistry\n function importContracts(address[] calldata _destinations) external onlyOwner {\n for (uint i = 0; i < _destinations.length;) {\n bytes32 name = Registrable(_destinations[i]).getName();\n registry[name] = _destinations[i];\n emit LogRegistered(_destinations[i], name);\n\n unchecked {\n i++;\n }\n }\n }\n\n /// @inheritdoc IRegistry\n function atomicUpdate(address _newContract) external onlyOwner {\n Registrable(_newContract).register();\n\n bytes32 name = Registrable(_newContract).getName();\n address oldContract = registry[name];\n registry[name] = _newContract;\n\n Registrable(oldContract).unregister();\n\n emit LogRegistered(_newContract, name);\n }\n\n /// @inheritdoc IRegistry\n function requireAndGetAddress(bytes32 name) external view returns (address) {\n address _foundAddress = registry[name];\n if (_foundAddress == address(0)) revert NameNotRegistered();\n\n return _foundAddress;\n }\n\n /// @inheritdoc IRegistry\n function getAddress(bytes32 _bytes) external view returns (address) {\n return registry[_bytes];\n }\n\n /// @inheritdoc IRegistry\n function getAddressByString(string memory _name) public view returns (address) {\n return registry[stringToBytes32(_name)];\n }\n\n /// @inheritdoc IRegistry\n function stringToBytes32(string memory _string) public pure returns (bytes32 result) {\n bytes memory tempEmptyStringTest = bytes(_string);\n\n if (tempEmptyStringTest.length == 0) {\n return 0x0;\n }\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n result := mload(add(_string, 32))\n }\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStatic.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/StakingBankStaticNotSupported.sol\";\n\n/// @dev Because we are using PoA in UMB oracle, staked balance does not matter. What's matter is, if signer is\n/// validator or not. In this case we can optimise `StakingBank` and make it static for better gas performance.\nabstract contract StakingBankStatic is StakingBankStaticNotSupported {\n uint256 public constant ONE = 1e18;\n\n uint256 public immutable NUMBER_OF_VALIDATORS; // solhint-disable-line var-name-mixedcase\n uint256 public immutable TOTAL_SUPPLY; // solhint-disable-line var-name-mixedcase\n\n constructor(uint256 _validatorsCount) {\n NUMBER_OF_VALIDATORS = _validatorsCount;\n TOTAL_SUPPLY = _validatorsCount * ONE;\n\n _assertValidSetup(_validatorsCount);\n }\n\n function balances(address _validator) external view returns (uint256) {\n return _isValidator(_validator) ? ONE : 0;\n }\n\n function verifyValidators(address[] calldata _validators) external view returns (bool) {\n for (uint256 i; i < _validators.length;) {\n if (!_isValidator(_validators[i])) return false;\n unchecked { i++; }\n }\n\n return true;\n }\n\n function getNumberOfValidators() external view returns (uint256) {\n return NUMBER_OF_VALIDATORS;\n }\n\n function getAddresses() external view returns (address[] memory) {\n return _addresses();\n }\n\n function getBalances() external view returns (uint256[] memory allBalances) {\n allBalances = new uint256[](NUMBER_OF_VALIDATORS);\n\n for (uint256 i; i < NUMBER_OF_VALIDATORS;) {\n allBalances[i] = ONE;\n\n unchecked {\n // we will not have enough data to overflow\n i++;\n }\n }\n }\n\n function addresses(uint256 _ix) external view returns (address) {\n return _addresses()[_ix];\n }\n\n function validators(address _id) external view virtual returns (address id, string memory location);\n\n /// @dev to follow ERC20 interface\n function balanceOf(address _account) external view returns (uint256) {\n return _isValidator(_account) ? ONE : 0;\n }\n\n /// @dev to follow ERC20 interface\n function totalSupply() external view returns (uint256) {\n return TOTAL_SUPPLY;\n }\n\n /// @dev to follow Registrable interface\n function getName() external pure returns (bytes32) {\n return \"StakingBank\";\n }\n\n /// @dev to follow Registrable interface\n function register() external pure {\n // there are no requirements atm\n }\n\n /// @dev to follow Registrable interface\n function unregister() external pure {\n // there are no requirements atm\n }\n\n function _addresses() internal view virtual returns (address[] memory);\n\n function _isValidator(address _validator) internal view virtual returns (bool);\n\n function _assertValidSetup(uint256 _validatorsCount) internal view virtual{\n address[] memory list = _addresses();\n require(list.length == _validatorsCount);\n\n for (uint256 i; i < _validatorsCount;) {\n require(_isValidator(list[i]));\n\n unchecked { i ++; }\n }\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticCI.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticCI is StakingBankStatic {\n // 0x87630b2d1de0fbd5044eb6891b3d9d98c34c8d310c852f98550ba774480e47cc\n address public constant VALIDATOR_0 = 0x2fFd013AaA7B5a7DA93336C2251075202b33FB2B;\n // 0x3f1e8b94c70206bf816c1ed0b15ad98bdf225ae4c6e7e4eee6cdbcf706fda2ae\n address public constant VALIDATOR_1 = 0x43158ea338Ff13D0bDa0c3EB969B9EA5a624E7Cc;\n // 0x5da6b84117504d06b5dcd52b990d76965d2882f4e5852eb610bc76e4209b10d7\n address public constant VALIDATOR_2 = 0x9Fd8DD0627b9A32399Fd115c4725C7e17BC40e6d;\n // 0x1e5012671de3332ad0b43661984e94ab0e405bffddc9d3e863055040bab354b8\n address public constant VALIDATOR_3 = 0xa3F3659E469b7aE0b249546338DEdc0b684edB05;\n // 0x0edc1e35ea7701ddac703286674e79f04addbf5d2f6162fabc19d39bd3dc6662\n address public constant VALIDATOR_4 = 0xB98A954B9036DF144d685E910bfbAEC6B33A8d11;\n // 0x23c601ae397441f3ef6f1075dcb0031ff17fb079837beadaf3c84d96c6f3e569\n address public constant VALIDATOR_5 = 0xE5904695748fe4A84b40b3fc79De2277660BD1D3;\n\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.ci.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.ci.umb.network\");\n if (_id == VALIDATOR_2) return (_id, \"https://validator3.ci.umb.network\");\n if (_id == VALIDATOR_3) return (_id, \"https://validator4.ci.umb.network\");\n if (_id == VALIDATOR_4) return (_id, \"https://validator5.ci.umb.network\");\n if (_id == VALIDATOR_5) return (_id, \"https://validator6.ci.umb.network\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n list[2] = VALIDATOR_2;\n list[3] = VALIDATOR_3;\n list[4] = VALIDATOR_4;\n list[5] = VALIDATOR_5;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0\n || _validator == VALIDATOR_1\n || _validator == VALIDATOR_2\n || _validator == VALIDATOR_3\n || _validator == VALIDATOR_4\n || _validator == VALIDATOR_5\n );\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticDev.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticDev is StakingBankStatic {\n address public constant VALIDATOR_0 = 0xDc3eBc37DA53A644D67E5E3b5BA4EEF88D969d5C;\n address public constant VALIDATOR_1 = 0x998cb7821e605cC16b6174e7C50E19ADb2Dd2fB0;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.dev.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.dev.umb.network\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0 || _validator == VALIDATOR_1);\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticLocal.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticLocal is StakingBankStatic {\n address public constant VALIDATOR_0 = 0xeAD9C93b79Ae7C1591b1FB5323BD777E86e150d4;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"localhost\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0);\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticProd.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\ncontract StakingBankStaticProd is StakingBankStatic {\n address public constant VALIDATOR_0 = 0x977Ba523420110e230643B772Fe9cF955e11dA7B;\n address public constant VALIDATOR_1 = 0xe2422b23e52bc13ebA04d7FbB9F332Deb43360fB;\n\n // external order is based on validators submits on AVAX for Apr 2023\n address public constant VALIDATOR_2 = 0x57F404aD75e371c1A539589C1eFCA12e0C6980AD;\n address public constant VALIDATOR_3 = 0xD56C6A4f64E0bD70260472d1DB6Cf5825858CB0d;\n address public constant VALIDATOR_4 = 0x93FdcAB283b0BcAc48157590af482E1CFd6af6aC;\n address public constant VALIDATOR_5 = 0xCd733E06B06083d52fC5867E8E3432aA5c103A38;\n address public constant VALIDATOR_6 = 0x42e210b110c6aa49CdfA7ceF1444Aa4719653111;\n address public constant VALIDATOR_7 = 0x501731c6a69803a53Ec6c3e12f293c247cE1092B;\n address public constant VALIDATOR_8 = 0x8bF9661F1b247522C75DD0FE84355aD2EfF27144;\n address public constant VALIDATOR_9 = 0x281754Ab58391A478B7aA4E7f39991CfB41118c4;\n address public constant VALIDATOR_10 = 0x57A51D5BDcE188c2295fCA3b4687475a54E65A02;\n address public constant VALIDATOR_11 = 0x2F85824B2B38F179E451988670935d315b5b9692;\n address public constant VALIDATOR_12 = 0xA7241994267682de4dE7Ef62f52dc2C783d1784B;\n address public constant VALIDATOR_13 = 0x6eEd457C20603EDAE50C3A112CAA1a9425321bD0;\n address public constant VALIDATOR_14 = 0xC5a7650c2725a7B6A39f15cb9FbffC7af357AFeb;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n // solhint-disable-next-line code-complexity\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.umb.network\");\n if (_id == VALIDATOR_2) return (_id, \"https://umbrella.artemahr.tech\");\n if (_id == VALIDATOR_3) return (_id, \"https://umb.vtabsolutions.com:3030\");\n if (_id == VALIDATOR_4) return (_id, \"https://umbrella.crazywhale.es\");\n if (_id == VALIDATOR_5) return (_id, \"https://umbrella-node.gateomega.com\");\n if (_id == VALIDATOR_6) return (_id, \"https://umb.anorak.technology\");\n if (_id == VALIDATOR_7) return (_id, \"https://umbrella.validator.infstones.io\");\n if (_id == VALIDATOR_8) return (_id, \"https://umb.hashkey.cloud\");\n if (_id == VALIDATOR_9) return (_id, \"http://umbrella.staking4all.org:3000\");\n if (_id == VALIDATOR_10) return (_id, \"http://5.161.78.230:3000\");\n if (_id == VALIDATOR_11) return (_id, \"https://umb-api.staking.rocks\");\n if (_id == VALIDATOR_12) return (_id, \"https://rpc.urbanhq.net\");\n if (_id == VALIDATOR_13) return (_id, \"https://umbrella-node.ankastake.com\");\n if (_id == VALIDATOR_14) return (_id, \"https://umbrella.tchambrella.com\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n list[2] = VALIDATOR_2;\n list[3] = VALIDATOR_3;\n list[4] = VALIDATOR_4;\n list[5] = VALIDATOR_5;\n list[6] = VALIDATOR_6;\n list[7] = VALIDATOR_7;\n list[8] = VALIDATOR_8;\n list[9] = VALIDATOR_9;\n list[10] = VALIDATOR_10;\n list[11] = VALIDATOR_11;\n list[12] = VALIDATOR_12;\n list[13] = VALIDATOR_13;\n list[14] = VALIDATOR_14;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (\n _validator == VALIDATOR_0\n || _validator == VALIDATOR_1\n || _validator == VALIDATOR_2\n || _validator == VALIDATOR_3\n || _validator == VALIDATOR_4\n || _validator == VALIDATOR_5\n || _validator == VALIDATOR_6\n || _validator == VALIDATOR_7\n || _validator == VALIDATOR_8\n || _validator == VALIDATOR_9\n || _validator == VALIDATOR_10\n || _validator == VALIDATOR_11\n || _validator == VALIDATOR_12\n || _validator == VALIDATOR_13\n || _validator == VALIDATOR_14\n );\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticSbx.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticSbx is StakingBankStatic {\n address public constant VALIDATOR_0 = 0xE3bDa0C6E1fBB111091Dfef6f22a673b20Ea5F50;\n address public constant VALIDATOR_1 = 0xc1773490F00963CBAb3841fc07C1a0796E658Ba2;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.sbx.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.sbx.umb.network\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0 || _validator == VALIDATOR_1);\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": false, + "runs": 0 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/bob_production/StakingBankStatic.json b/deployments/bob_production/StakingBankStatic.json index 0c6e01f1..0482bc6b 100644 --- a/deployments/bob_production/StakingBankStatic.json +++ b/deployments/bob_production/StakingBankStatic.json @@ -1,5 +1,5 @@ { - "address": "0x6fC13EACE26590B80cCCAB1ba5d51890577D83B2", + "address": "0x150368e6bF2538B9Be8e5688F1D7457773C49463", "abi": [ { "inputs": [ @@ -249,58 +249,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "VALIDATOR_15", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATOR_16", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATOR_17", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATOR_18", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "VALIDATOR_2", @@ -812,30 +760,30 @@ "type": "function" } ], - "transactionHash": "0x21eb14725271c0741faa8699a2d0c0f74eb0aab7dd92d571ad95ee28541f166c", + "transactionHash": "0x1746ab0d6c5bcb2ca7b28e0e4f32d09b05cad0aa8ae54681538a0f8a073f265c", "receipt": { "to": null, "from": "0xA6e4fFa19B213AbeA258ae72e8e1a209B9E543e7", - "contractAddress": "0x6fC13EACE26590B80cCCAB1ba5d51890577D83B2", - "transactionIndex": 1, - "gasUsed": "2644122", + "contractAddress": "0x150368e6bF2538B9Be8e5688F1D7457773C49463", + "transactionIndex": 3, + "gasUsed": "2301671", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xe4e7d66bf73574844e67a9ecc9b9713247a10866706620fbe41699c8c793c18c", - "transactionHash": "0x21eb14725271c0741faa8699a2d0c0f74eb0aab7dd92d571ad95ee28541f166c", + "blockHash": "0x336e0b686fb7ac9ba66fb031e8dab92c2a109fc55ddcefd826d0d9146a8a6fa1", + "transactionHash": "0x1746ab0d6c5bcb2ca7b28e0e4f32d09b05cad0aa8ae54681538a0f8a073f265c", "logs": [], - "blockNumber": 7475700, - "cumulativeGasUsed": "2693573", + "blockNumber": 8710178, + "cumulativeGasUsed": "2653241", "status": 1, "byzantium": true }, "args": [ - 19 + 15 ], - "numDeployments": 1, - "solcInputHash": "c45d125781228a2640f2fc0eee67ec9d", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_validatorsCount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"NotSupported\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"minAmountForStake\",\"type\":\"uint256\"}],\"name\":\"LogMinAmountForStake\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"NUMBER_OF_VALIDATORS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ONE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TOTAL_SUPPLY\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_0\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_1\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_10\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_11\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_12\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_13\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_14\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_15\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_16\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_17\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_18\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_2\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_3\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_4\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_5\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_6\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_7\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_8\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_9\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_ix\",\"type\":\"uint256\"}],\"name\":\"addresses\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validator\",\"type\":\"address\"}],\"name\":\"balances\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"create\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"exit\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBalances\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"allBalances\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumberOfValidators\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"receiveApproval\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"register\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"remove\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"setMinAmountForStake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"stake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"update\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_id\",\"type\":\"address\"}],\"name\":\"validators\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"location\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_validators\",\"type\":\"address[]\"}],\"name\":\"verifyValidators\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addresses(uint256)\":{\"details\":\"gets validator address for provided index\",\"params\":{\"_ix\":\"index in array of list of all validators wallets\"}},\"balanceOf(address)\":{\"details\":\"to follow ERC20 interface\"},\"exit()\":{\"details\":\"unstake and withdraw all tokens\"},\"getName()\":{\"details\":\"to follow Registrable interface\"},\"getNumberOfValidators()\":{\"returns\":{\"_0\":\"total number of registered validators (with and without balance)\"}},\"register()\":{\"details\":\"to follow Registrable interface\"},\"totalSupply()\":{\"details\":\"to follow ERC20 interface\"},\"unregister()\":{\"details\":\"to follow Registrable interface\"},\"validators(address)\":{\"params\":{\"_id\":\"address of validator\"},\"returns\":{\"id\":\"address of validator\",\"location\":\"URL of validator\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":\"StakingBankStaticProd\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":0},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBank.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IStakingBank is IERC20 {\\n /// @param id address of validator wallet\\n /// @param location URL of the validator API\\n struct Validator {\\n address id;\\n string location;\\n }\\n\\n event LogValidatorRegistered(address indexed id);\\n event LogValidatorUpdated(address indexed id);\\n event LogValidatorRemoved(address indexed id);\\n event LogMinAmountForStake(uint256 minAmountForStake);\\n\\n /// @dev setter for `minAmountForStake`\\n function setMinAmountForStake(uint256 _minAmountForStake) external;\\n\\n /// @dev allows to stake `token` by validators\\n /// Validator needs to approve StakingBank beforehand\\n /// @param _value amount of tokens to stake\\n function stake(uint256 _value) external;\\n\\n /// @dev notification about approval from `_from` address on UMB token\\n /// Staking bank will stake max approved amount from `_from` address\\n /// @param _from address which approved token spend for IStakingBank\\n function receiveApproval(address _from) external returns (bool success);\\n\\n /// @dev withdraws stake tokens\\n /// it throws, when balance will be less than required minimum for stake\\n /// to withdraw all use `exit`\\n function withdraw(uint256 _value) external returns (bool success);\\n\\n /// @dev unstake and withdraw all tokens\\n function exit() external returns (bool success);\\n\\n /// @dev creates (register) new validator\\n /// @param _id validator address\\n /// @param _location location URL of the validator API\\n function create(address _id, string calldata _location) external;\\n\\n /// @dev removes validator\\n /// @param _id validator wallet\\n function remove(address _id) external;\\n\\n /// @dev updates validator location\\n /// @param _id validator wallet\\n /// @param _location new validator URL\\n function update(address _id, string calldata _location) external;\\n\\n /// @return total number of registered validators (with and without balance)\\n function getNumberOfValidators() external view returns (uint256);\\n\\n /// @dev gets validator address for provided index\\n /// @param _ix index in array of list of all validators wallets\\n function addresses(uint256 _ix) external view returns (address);\\n\\n /// @param _id address of validator\\n /// @return id address of validator\\n /// @return location URL of validator\\n function validators(address _id) external view returns (address id, string memory location);\\n}\\n\",\"keccak256\":\"0x2c518aeab8b0b3a364fafaec559d3ff0dc6a119f8d203fa31ef7ad667ca0f7b9\",\"license\":\"MIT\"},\"contracts/interfaces/StakingBankStaticNotSupported.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./IStakingBank.sol\\\";\\n\\nabstract contract StakingBankStaticNotSupported is IStakingBank {\\n error NotSupported();\\n\\n function create(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function update(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function remove(address) external pure {\\n revert NotSupported();\\n }\\n\\n function transfer(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function transferFrom(address, address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function receiveApproval(address) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function allowance(address, address) external pure returns (uint256) {\\n revert NotSupported();\\n }\\n\\n function approve(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function stake(uint256) external pure {\\n revert NotSupported();\\n }\\n\\n function withdraw(uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function exit() external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function setMinAmountForStake(uint256) external pure {\\n revert NotSupported();\\n }\\n}\\n\",\"keccak256\":\"0xa899ad9000220b04bc3f63f762a9a6a76dcc09449427e7774a53f4ceda9c1cf8\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStatic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"../interfaces/StakingBankStaticNotSupported.sol\\\";\\n\\n/// @dev Because we are using PoA in UMB oracle, staked balance does not matter. What's matter is, if signer is\\n/// validator or not. In this case we can optimise `StakingBank` and make it static for better gas performance.\\nabstract contract StakingBankStatic is StakingBankStaticNotSupported {\\n uint256 public constant ONE = 1e18;\\n\\n uint256 public immutable NUMBER_OF_VALIDATORS; // solhint-disable-line var-name-mixedcase\\n uint256 public immutable TOTAL_SUPPLY; // solhint-disable-line var-name-mixedcase\\n\\n constructor(uint256 _validatorsCount) {\\n NUMBER_OF_VALIDATORS = _validatorsCount;\\n TOTAL_SUPPLY = _validatorsCount * ONE;\\n\\n _assertValidSetup(_validatorsCount);\\n }\\n\\n function balances(address _validator) external view returns (uint256) {\\n return _isValidator(_validator) ? ONE : 0;\\n }\\n\\n function verifyValidators(address[] calldata _validators) external view returns (bool) {\\n for (uint256 i; i < _validators.length;) {\\n if (!_isValidator(_validators[i])) return false;\\n unchecked { i++; }\\n }\\n\\n return true;\\n }\\n\\n function getNumberOfValidators() external view returns (uint256) {\\n return NUMBER_OF_VALIDATORS;\\n }\\n\\n function getAddresses() external view returns (address[] memory) {\\n return _addresses();\\n }\\n\\n function getBalances() external view returns (uint256[] memory allBalances) {\\n allBalances = new uint256[](NUMBER_OF_VALIDATORS);\\n\\n for (uint256 i; i < NUMBER_OF_VALIDATORS;) {\\n allBalances[i] = ONE;\\n\\n unchecked {\\n // we will not have enough data to overflow\\n i++;\\n }\\n }\\n }\\n\\n function addresses(uint256 _ix) external view returns (address) {\\n return _addresses()[_ix];\\n }\\n\\n function validators(address _id) external view virtual returns (address id, string memory location);\\n\\n /// @dev to follow ERC20 interface\\n function balanceOf(address _account) external view returns (uint256) {\\n return _isValidator(_account) ? ONE : 0;\\n }\\n\\n /// @dev to follow ERC20 interface\\n function totalSupply() external view returns (uint256) {\\n return TOTAL_SUPPLY;\\n }\\n\\n /// @dev to follow Registrable interface\\n function getName() external pure returns (bytes32) {\\n return \\\"StakingBank\\\";\\n }\\n\\n /// @dev to follow Registrable interface\\n function register() external pure {\\n // there are no requirements atm\\n }\\n\\n /// @dev to follow Registrable interface\\n function unregister() external pure {\\n // there are no requirements atm\\n }\\n\\n function _addresses() internal view virtual returns (address[] memory);\\n\\n function _isValidator(address _validator) internal view virtual returns (bool);\\n\\n function _assertValidSetup(uint256 _validatorsCount) internal view virtual{\\n address[] memory list = _addresses();\\n require(list.length == _validatorsCount);\\n\\n for (uint256 i; i < _validatorsCount;) {\\n require(_isValidator(list[i]));\\n\\n unchecked { i ++; }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfcc53ff98b0f1c42e1bc7345a1535fdc4e938ef40d323600ead94b2ece59a381\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./StakingBankStatic.sol\\\";\\n\\ncontract StakingBankStaticProd is StakingBankStatic {\\n address public constant VALIDATOR_0 = 0x977Ba523420110e230643B772Fe9cF955e11dA7B;\\n address public constant VALIDATOR_1 = 0xe2422b23e52bc13ebA04d7FbB9F332Deb43360fB;\\n\\n // external order is based on validators submits on AVAX for Apr 2023\\n address public constant VALIDATOR_2 = 0x57F404aD75e371c1A539589C1eFCA12e0C6980AD;\\n address public constant VALIDATOR_3 = 0xD56C6A4f64E0bD70260472d1DB6Cf5825858CB0d;\\n address public constant VALIDATOR_4 = 0x220230Eda8f50067Dd9e4729345dabCCe0C61542;\\n address public constant VALIDATOR_5 = 0x93FdcAB283b0BcAc48157590af482E1CFd6af6aC;\\n address public constant VALIDATOR_6 = 0xCd733E06B06083d52fC5867E8E3432aA5c103A38;\\n address public constant VALIDATOR_7 = 0x42e210b110c6aa49CdfA7ceF1444Aa4719653111;\\n address public constant VALIDATOR_8 = 0x501731c6a69803a53Ec6c3e12f293c247cE1092B;\\n address public constant VALIDATOR_9 = 0x8bF9661F1b247522C75DD0FE84355aD2EfF27144;\\n address public constant VALIDATOR_10 = 0x281754Ab58391A478B7aA4E7f39991CfB41118c4;\\n address public constant VALIDATOR_11 = 0xB9C63a350A04d8BD245d18928a26EE036352dDd8;\\n address public constant VALIDATOR_12 = 0x57A51D5BDcE188c2295fCA3b4687475a54E65A02;\\n address public constant VALIDATOR_13 = 0x777FbA3666fa7747476a34577FcCC404b263E09F;\\n address public constant VALIDATOR_14 = 0x2F85824B2B38F179E451988670935d315b5b9692;\\n address public constant VALIDATOR_15 = 0xA7241994267682de4dE7Ef62f52dc2C783d1784B;\\n address public constant VALIDATOR_16 = 0x6eEd457C20603EDAE50C3A112CAA1a9425321bD0;\\n address public constant VALIDATOR_17 = 0xC5a7650c2725a7B6A39f15cb9FbffC7af357AFeb;\\n address public constant VALIDATOR_18 = 0xFEd95453678920c1b7b3A81F033Ca02a27225556;\\n\\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\\n\\n // solhint-disable-next-line code-complexity\\n function validators(address _id) external pure override returns (address id, string memory location) {\\n if (_id == VALIDATOR_0) return (_id, \\\"https://validator.umb.network\\\");\\n if (_id == VALIDATOR_1) return (_id, \\\"https://validator2.umb.network\\\");\\n if (_id == VALIDATOR_2) return (_id, \\\"https://umbrella.artemahr.tech\\\");\\n if (_id == VALIDATOR_3) return (_id, \\\"https://umb.vtabsolutions.com:3030\\\");\\n if (_id == VALIDATOR_4) return (_id, \\\"https://umb.stakers.world\\\");\\n if (_id == VALIDATOR_5) return (_id, \\\"https://umbrella.crazywhale.es\\\");\\n if (_id == VALIDATOR_6) return (_id, \\\"https://umbrella-node.gateomega.com\\\");\\n if (_id == VALIDATOR_7) return (_id, \\\"https://umb.anorak.technology\\\");\\n if (_id == VALIDATOR_8) return (_id, \\\"https://umbrella.validator.infstones.io\\\");\\n if (_id == VALIDATOR_9) return (_id, \\\"https://umb.hashquark.io\\\");\\n if (_id == VALIDATOR_10) return (_id, \\\"http://umbrella.staking4all.org:3000\\\");\\n if (_id == VALIDATOR_11) return (_id, \\\"https://umbrella-api.validatrium.club\\\");\\n if (_id == VALIDATOR_12) return (_id, \\\"http://5.161.78.230:3000\\\");\\n if (_id == VALIDATOR_13) return (_id, \\\"https://umbnode.blockchainliverpool.com\\\");\\n if (_id == VALIDATOR_14) return (_id, \\\"https://umb-api.staking.rocks\\\");\\n if (_id == VALIDATOR_15) return (_id, \\\"https://rpc.urbanhq.net\\\");\\n if (_id == VALIDATOR_16) return (_id, \\\"https://umbrella-node.ankastake.com\\\");\\n if (_id == VALIDATOR_17) return (_id, \\\"https://umbrella.tchambrella.com\\\");\\n if (_id == VALIDATOR_18) return (_id, \\\"https://umbrella-node.cmt13.eu\\\");\\n\\n return (address(0), \\\"\\\");\\n }\\n\\n function _addresses() internal view override returns (address[] memory) {\\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\\n\\n list[0] = VALIDATOR_0;\\n list[1] = VALIDATOR_1;\\n list[2] = VALIDATOR_2;\\n list[3] = VALIDATOR_3;\\n list[4] = VALIDATOR_4;\\n list[5] = VALIDATOR_5;\\n list[6] = VALIDATOR_6;\\n list[7] = VALIDATOR_7;\\n list[8] = VALIDATOR_8;\\n list[9] = VALIDATOR_9;\\n list[10] = VALIDATOR_10;\\n list[11] = VALIDATOR_11;\\n list[12] = VALIDATOR_12;\\n list[13] = VALIDATOR_13;\\n list[14] = VALIDATOR_14;\\n list[15] = VALIDATOR_15;\\n list[16] = VALIDATOR_16;\\n list[17] = VALIDATOR_17;\\n list[18] = VALIDATOR_18;\\n\\n return list;\\n }\\n\\n function _isValidator(address _validator) internal pure override returns (bool) {\\n return (\\n _validator == VALIDATOR_0\\n || _validator == VALIDATOR_1\\n || _validator == VALIDATOR_2\\n || _validator == VALIDATOR_3\\n || _validator == VALIDATOR_4\\n || _validator == VALIDATOR_5\\n || _validator == VALIDATOR_6\\n || _validator == VALIDATOR_7\\n || _validator == VALIDATOR_8\\n || _validator == VALIDATOR_9\\n || _validator == VALIDATOR_10\\n || _validator == VALIDATOR_11\\n || _validator == VALIDATOR_12\\n || _validator == VALIDATOR_13\\n || _validator == VALIDATOR_14\\n || _validator == VALIDATOR_15\\n || _validator == VALIDATOR_16\\n || _validator == VALIDATOR_17\\n || _validator == VALIDATOR_18\\n );\\n }\\n}\\n\",\"keccak256\":\"0x1e80a063f381fdb75109238bd1e4db75af37b5aea8d8165293aee4bf84838c85\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60c06040523480156200001157600080fd5b5060405162003da238038062003da2833981810160405281019062000037919062000eaf565b808060808181525050670de0b6b3a76400008162000056919062000f10565b60a081815250506200006e816200007660201b60201c565b505062000fcf565b600062000088620000ef60201b60201c565b9050818151146200009857600080fd5b60005b82811015620000ea57620000d2828281518110620000be57620000bd62000f71565b5b6020026020010151620008dd60201b60201c565b620000dc57600080fd5b80806001019150506200009b565b505050565b6060600060805167ffffffffffffffff81111562000112576200011162000fa0565b5b604051908082528060200260200182016040528015620001415781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b8160008151811062000170576200016f62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110620001d657620001d562000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad816002815181106200023c576200023b62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110620002a257620002a162000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073220230eda8f50067dd9e4729345dabcce0c615428160048151811062000308576200030762000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac816005815181106200036e576200036d62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a3881600681518110620003d457620003d362000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa4719653111816007815181106200043a576200043962000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b81600881518110620004a0576200049f62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff271448160098151811062000506576200050562000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600a815181106200056c576200056b62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073b9c63a350a04d8bd245d18928a26ee036352ddd881600b81518110620005d257620005d162000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600c8151811062000638576200063762000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073777fba3666fa7747476a34577fccc404b263e09f81600d815181106200069e576200069d62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600e8151811062000704576200070362000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600f815181106200076a576200076962000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081601081518110620007d057620007cf62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb8160118151811062000836576200083562000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073fed95453678920c1b7b3a81f033ca02a27225556816012815181106200089c576200089b62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806200096d575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80620009b857507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a03575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a4e575073220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a9957507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ae4575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b2f57507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b7a575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000bc55750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000c10575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000c5b575073b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ca657507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000cf1575073777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000d3c5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000d87575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000dd25750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000e1d575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000e68575073fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b600080fd5b6000819050919050565b62000e898162000e74565b811462000e9557600080fd5b50565b60008151905062000ea98162000e7e565b92915050565b60006020828403121562000ec85762000ec762000e6f565b5b600062000ed88482850162000e98565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600062000f1d8262000e74565b915062000f2a8362000e74565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161562000f665762000f6562000ee1565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60805160a051612d8a62001018600039600081816109ac0152610c2e01526000818161081b0152818161088901528181610c5401528181610dbd0152611db40152612d8a6000f3fe608060405234801561001057600080fd5b50600436106102195760003560e01c8062113e081461021e578063015f7ed61461023c57806303a1e2241461025a578063095ea7b3146102785780630db18e37146102a857806317d7de7c146102d857806318160ddd146102f65780631aa3a008146103145780631d4f9ce01461031e57806323b872dd1461034e57806327e235e31461037e57806329092d0e146103ae5780632e1a7d4d146103ca578063398b056e146103fa578063411ff4971461041857806345f9f8251461043657806352b41e351461045457806354755335146104705780635dc4bfd31461048e57806361a3e37e146104ac57806369dc7ae4146104ca57806370a08231146104e8578063838e7c3a14610518578063902d55a5146105345780639031d9131461055257806390ff7e2e14610570578063952c4f181461058e578063989b6996146105ac5780639f0e9484146105ca578063a15ab08d146105e8578063a39fac1214610604578063a694fc3a14610622578063a9059cbb1461063e578063b2119eac1461066e578063b49b08421461068c578063c2ee3a08146106aa578063db731777146106c8578063dd62ed3e146106e6578063e214a5fc14610716578063e29349d614610734578063e2dc7a1a14610752578063e79a198f14610770578063e985e0081461077a578063e9fad8ee14610798578063edf26d9b146107b6578063fa52c7d8146107e6575b600080fd5b610226610817565b6040516102339190612645565b60405180910390f35b6102446108e8565b60405161025191906126a8565b60405180910390f35b610262610900565b60405161026f91906126a8565b60405180910390f35b610292600480360381019061028d9190612725565b610918565b60405161029f9190612780565b60405180910390f35b6102c260048036038101906102bd919061279b565b61094c565b6040516102cf9190612780565b60405180910390f35b6102e0610980565b6040516102ed91906127e1565b60405180910390f35b6102fe6109a8565b60405161030b919061280b565b60405180910390f35b61031c6109d0565b005b6103386004803603810190610333919061288b565b6109d2565b6040516103459190612780565b60405180910390f35b610368600480360381019061036391906128d8565b610a38565b6040516103759190612780565b60405180910390f35b6103986004803603810190610393919061279b565b610a6c565b6040516103a5919061280b565b60405180910390f35b6103c860048036038101906103c3919061279b565b610a93565b005b6103e460048036038101906103df919061292b565b610ac5565b6040516103f19190612780565b60405180910390f35b610402610af9565b60405161040f91906126a8565b60405180910390f35b610420610b11565b60405161042d91906126a8565b60405180910390f35b61043e610b29565b60405161044b91906126a8565b60405180910390f35b61046e6004803603810190610469919061292b565b610b41565b005b610478610b73565b60405161048591906126a8565b60405180910390f35b610496610b8b565b6040516104a391906126a8565b60405180910390f35b6104b4610ba3565b6040516104c191906126a8565b60405180910390f35b6104d2610bbb565b6040516104df91906126a8565b60405180910390f35b61050260048036038101906104fd919061279b565b610bd3565b60405161050f919061280b565b60405180910390f35b610532600480360381019061052d91906129ae565b610bfa565b005b61053c610c2c565b604051610549919061280b565b60405180910390f35b61055a610c50565b604051610567919061280b565b60405180910390f35b610578610c78565b60405161058591906126a8565b60405180910390f35b610596610c90565b6040516105a391906126a8565b60405180910390f35b6105b4610ca8565b6040516105c191906126a8565b60405180910390f35b6105d2610cc0565b6040516105df91906126a8565b60405180910390f35b61060260048036038101906105fd91906129ae565b610cd8565b005b61060c610d0a565b6040516106199190612acc565b60405180910390f35b61063c6004803603810190610637919061292b565b610d19565b005b61065860048036038101906106539190612725565b610d4b565b6040516106659190612780565b60405180910390f35b610676610d7f565b60405161068391906126a8565b60405180910390f35b610694610d97565b6040516106a191906126a8565b60405180910390f35b6106b2610daf565b6040516106bf919061280b565b60405180910390f35b6106d0610dbb565b6040516106dd919061280b565b60405180910390f35b61070060048036038101906106fb9190612aee565b610ddf565b60405161070d919061280b565b60405180910390f35b61071e610e13565b60405161072b91906126a8565b60405180910390f35b61073c610e2b565b60405161074991906126a8565b60405180910390f35b61075a610e43565b60405161076791906126a8565b60405180910390f35b610778610e5b565b005b610782610e5d565b60405161078f91906126a8565b60405180910390f35b6107a0610e75565b6040516107ad9190612780565b60405180910390f35b6107d060048036038101906107cb919061292b565b610ea9565b6040516107dd91906126a8565b60405180910390f35b61080060048036038101906107fb919061279b565b610ed4565b60405161080e929190612bc7565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff81111561085357610852612bf7565b5b6040519080825280602002602001820160405280156108815781602001602082028036833780820191505090505b50905060005b7f00000000000000000000000000000000000000000000000000000000000000008110156108e457670de0b6b3a76400008282815181106108cb576108ca612c26565b5b6020026020010181815250508080600101915050610887565b5090565b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b83839050811015610a2c57610a118484838181106109f7576109f6612c26565b5b9050602002016020810190610a0c919061279b565b61182e565b610a1f576000915050610a32565b80806001019150506109d6565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a778261182e565b610a82576000610a8c565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b732f85824b2b38f179e451988670935d315b5b969281565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b73fed95453678920c1b7b3a81f033ca02a2722555681565b73777fba3666fa7747476a34577fccc404b263e09f81565b6000610bde8261182e565b610be9576000610bf3565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b73220230eda8f50067dd9e4729345dabcce0c6154281565b73a7241994267682de4de7ef62f52dc2c783d1784b81565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610d14611dae565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73281754ab58391a478b7aa4e7f39991cfb41118c481565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b736eed457c20603edae50c3a112caa1a9425321bd081565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b565b73b9c63a350a04d8bd245d18928a26ee036352ddd881565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610eb3611dae565b8281518110610ec557610ec4612c26565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f5f57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611829565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fe657826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611829565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361106d57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611829565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110d75782604051806060016040528060228152602001612c796022913991509150611829565b73220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361115e57826040518060400160405280601981526020017f68747470733a2f2f756d622e7374616b6572732e776f726c640000000000000081525091509150611829565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111e557826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611829565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361124f5782604051806060016040528060238152602001612c566023913991509150611829565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112d657826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611829565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113405782604051806060016040528060278152602001612cbf6027913991509150611829565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113c757826040518060400160405280601881526020017f68747470733a2f2f756d622e68617368717561726b2e696f000000000000000081525091509150611829565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114315782604051806060016040528060248152602001612c9b6024913991509150611829565b73b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361149b5782604051806060016040528060258152602001612ce66025913991509150611829565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152257826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611829565b73777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361158c5782604051806060016040528060278152602001612d2e6027913991509150611829565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361161357826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611829565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361169a57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611829565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036117045782604051806060016040528060238152602001612d0b6023913991509150611829565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361178b57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611829565b73fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361181257826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612d6e6f64652e636d7431332e6575000081525091509150611829565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806118bd575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061190757507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611951575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061199b575073220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806119e557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a2f575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a7957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ac3575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b0d5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b57575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ba1575073b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611beb57507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c35575073777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c7f5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611cc9575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d135750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d5d575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611da7575073fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff811115611dec57611deb612bf7565b5b604051908082528060200260200182016040528015611e1a5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611e4657611e45612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611ea957611ea8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611f0c57611f0b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611f6f57611f6e612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073220230eda8f50067dd9e4729345dabcce0c6154281600481518110611fd257611fd1612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac8160058151811061203557612034612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a388160068151811061209857612097612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa4719653111816007815181106120fb576120fa612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b8160088151811061215e5761215d612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff27144816009815181106121c1576121c0612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600a8151811061222457612223612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073b9c63a350a04d8bd245d18928a26ee036352ddd881600b8151811061228757612286612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600c815181106122ea576122e9612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073777fba3666fa7747476a34577fccc404b263e09f81600d8151811061234d5761234c612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600e815181106123b0576123af612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600f8151811061241357612412612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd08160108151811061247657612475612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb816011815181106124d9576124d8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073fed95453678920c1b7b3a81f033ca02a272255568160128151811061253c5761253b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6125bc816125a9565b82525050565b60006125ce83836125b3565b60208301905092915050565b6000602082019050919050565b60006125f28261257d565b6125fc8185612588565b935061260783612599565b8060005b8381101561263857815161261f88826125c2565b975061262a836125da565b92505060018101905061260b565b5085935050505092915050565b6000602082019050818103600083015261265f81846125e7565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061269282612667565b9050919050565b6126a281612687565b82525050565b60006020820190506126bd6000830184612699565b92915050565b600080fd5b600080fd5b6126d681612687565b81146126e157600080fd5b50565b6000813590506126f3816126cd565b92915050565b612702816125a9565b811461270d57600080fd5b50565b60008135905061271f816126f9565b92915050565b6000806040838503121561273c5761273b6126c3565b5b600061274a858286016126e4565b925050602061275b85828601612710565b9150509250929050565b60008115159050919050565b61277a81612765565b82525050565b60006020820190506127956000830184612771565b92915050565b6000602082840312156127b1576127b06126c3565b5b60006127bf848285016126e4565b91505092915050565b6000819050919050565b6127db816127c8565b82525050565b60006020820190506127f660008301846127d2565b92915050565b612805816125a9565b82525050565b600060208201905061282060008301846127fc565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261284b5761284a612826565b5b8235905067ffffffffffffffff8111156128685761286761282b565b5b60208301915083602082028301111561288457612883612830565b5b9250929050565b600080602083850312156128a2576128a16126c3565b5b600083013567ffffffffffffffff8111156128c0576128bf6126c8565b5b6128cc85828601612835565b92509250509250929050565b6000806000606084860312156128f1576128f06126c3565b5b60006128ff868287016126e4565b9350506020612910868287016126e4565b925050604061292186828701612710565b9150509250925092565b600060208284031215612941576129406126c3565b5b600061294f84828501612710565b91505092915050565b60008083601f84011261296e5761296d612826565b5b8235905067ffffffffffffffff81111561298b5761298a61282b565b5b6020830191508360018202830111156129a7576129a6612830565b5b9250929050565b6000806000604084860312156129c7576129c66126c3565b5b60006129d5868287016126e4565b935050602084013567ffffffffffffffff8111156129f6576129f56126c8565b5b612a0286828701612958565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b612a4381612687565b82525050565b6000612a558383612a3a565b60208301905092915050565b6000602082019050919050565b6000612a7982612a0e565b612a838185612a19565b9350612a8e83612a2a565b8060005b83811015612abf578151612aa68882612a49565b9750612ab183612a61565b925050600181019050612a92565b5085935050505092915050565b60006020820190508181036000830152612ae68184612a6e565b905092915050565b60008060408385031215612b0557612b046126c3565b5b6000612b13858286016126e4565b9250506020612b24858286016126e4565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612b68578082015181840152602081019050612b4d565b83811115612b77576000848401525b50505050565b6000601f19601f8301169050919050565b6000612b9982612b2e565b612ba38185612b39565b9350612bb3818560208601612b4a565b612bbc81612b7d565b840191505092915050565b6000604082019050612bdc6000830185612699565b8181036020830152612bee8184612b8e565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6170692e76616c696461747269756d2e636c756268747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6d68747470733a2f2f756d626e6f64652e626c6f636b636861696e6c69766572706f6f6c2e636f6da26469706673582212209a1752a9ea487818b8a4d658f151da9487c0cc92638142159bacde7ec2d21f7564736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102195760003560e01c8062113e081461021e578063015f7ed61461023c57806303a1e2241461025a578063095ea7b3146102785780630db18e37146102a857806317d7de7c146102d857806318160ddd146102f65780631aa3a008146103145780631d4f9ce01461031e57806323b872dd1461034e57806327e235e31461037e57806329092d0e146103ae5780632e1a7d4d146103ca578063398b056e146103fa578063411ff4971461041857806345f9f8251461043657806352b41e351461045457806354755335146104705780635dc4bfd31461048e57806361a3e37e146104ac57806369dc7ae4146104ca57806370a08231146104e8578063838e7c3a14610518578063902d55a5146105345780639031d9131461055257806390ff7e2e14610570578063952c4f181461058e578063989b6996146105ac5780639f0e9484146105ca578063a15ab08d146105e8578063a39fac1214610604578063a694fc3a14610622578063a9059cbb1461063e578063b2119eac1461066e578063b49b08421461068c578063c2ee3a08146106aa578063db731777146106c8578063dd62ed3e146106e6578063e214a5fc14610716578063e29349d614610734578063e2dc7a1a14610752578063e79a198f14610770578063e985e0081461077a578063e9fad8ee14610798578063edf26d9b146107b6578063fa52c7d8146107e6575b600080fd5b610226610817565b6040516102339190612645565b60405180910390f35b6102446108e8565b60405161025191906126a8565b60405180910390f35b610262610900565b60405161026f91906126a8565b60405180910390f35b610292600480360381019061028d9190612725565b610918565b60405161029f9190612780565b60405180910390f35b6102c260048036038101906102bd919061279b565b61094c565b6040516102cf9190612780565b60405180910390f35b6102e0610980565b6040516102ed91906127e1565b60405180910390f35b6102fe6109a8565b60405161030b919061280b565b60405180910390f35b61031c6109d0565b005b6103386004803603810190610333919061288b565b6109d2565b6040516103459190612780565b60405180910390f35b610368600480360381019061036391906128d8565b610a38565b6040516103759190612780565b60405180910390f35b6103986004803603810190610393919061279b565b610a6c565b6040516103a5919061280b565b60405180910390f35b6103c860048036038101906103c3919061279b565b610a93565b005b6103e460048036038101906103df919061292b565b610ac5565b6040516103f19190612780565b60405180910390f35b610402610af9565b60405161040f91906126a8565b60405180910390f35b610420610b11565b60405161042d91906126a8565b60405180910390f35b61043e610b29565b60405161044b91906126a8565b60405180910390f35b61046e6004803603810190610469919061292b565b610b41565b005b610478610b73565b60405161048591906126a8565b60405180910390f35b610496610b8b565b6040516104a391906126a8565b60405180910390f35b6104b4610ba3565b6040516104c191906126a8565b60405180910390f35b6104d2610bbb565b6040516104df91906126a8565b60405180910390f35b61050260048036038101906104fd919061279b565b610bd3565b60405161050f919061280b565b60405180910390f35b610532600480360381019061052d91906129ae565b610bfa565b005b61053c610c2c565b604051610549919061280b565b60405180910390f35b61055a610c50565b604051610567919061280b565b60405180910390f35b610578610c78565b60405161058591906126a8565b60405180910390f35b610596610c90565b6040516105a391906126a8565b60405180910390f35b6105b4610ca8565b6040516105c191906126a8565b60405180910390f35b6105d2610cc0565b6040516105df91906126a8565b60405180910390f35b61060260048036038101906105fd91906129ae565b610cd8565b005b61060c610d0a565b6040516106199190612acc565b60405180910390f35b61063c6004803603810190610637919061292b565b610d19565b005b61065860048036038101906106539190612725565b610d4b565b6040516106659190612780565b60405180910390f35b610676610d7f565b60405161068391906126a8565b60405180910390f35b610694610d97565b6040516106a191906126a8565b60405180910390f35b6106b2610daf565b6040516106bf919061280b565b60405180910390f35b6106d0610dbb565b6040516106dd919061280b565b60405180910390f35b61070060048036038101906106fb9190612aee565b610ddf565b60405161070d919061280b565b60405180910390f35b61071e610e13565b60405161072b91906126a8565b60405180910390f35b61073c610e2b565b60405161074991906126a8565b60405180910390f35b61075a610e43565b60405161076791906126a8565b60405180910390f35b610778610e5b565b005b610782610e5d565b60405161078f91906126a8565b60405180910390f35b6107a0610e75565b6040516107ad9190612780565b60405180910390f35b6107d060048036038101906107cb919061292b565b610ea9565b6040516107dd91906126a8565b60405180910390f35b61080060048036038101906107fb919061279b565b610ed4565b60405161080e929190612bc7565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff81111561085357610852612bf7565b5b6040519080825280602002602001820160405280156108815781602001602082028036833780820191505090505b50905060005b7f00000000000000000000000000000000000000000000000000000000000000008110156108e457670de0b6b3a76400008282815181106108cb576108ca612c26565b5b6020026020010181815250508080600101915050610887565b5090565b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b83839050811015610a2c57610a118484838181106109f7576109f6612c26565b5b9050602002016020810190610a0c919061279b565b61182e565b610a1f576000915050610a32565b80806001019150506109d6565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a778261182e565b610a82576000610a8c565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b732f85824b2b38f179e451988670935d315b5b969281565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b73fed95453678920c1b7b3a81f033ca02a2722555681565b73777fba3666fa7747476a34577fccc404b263e09f81565b6000610bde8261182e565b610be9576000610bf3565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b73220230eda8f50067dd9e4729345dabcce0c6154281565b73a7241994267682de4de7ef62f52dc2c783d1784b81565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610d14611dae565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73281754ab58391a478b7aa4e7f39991cfb41118c481565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b736eed457c20603edae50c3a112caa1a9425321bd081565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b565b73b9c63a350a04d8bd245d18928a26ee036352ddd881565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610eb3611dae565b8281518110610ec557610ec4612c26565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f5f57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611829565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fe657826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611829565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361106d57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611829565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110d75782604051806060016040528060228152602001612c796022913991509150611829565b73220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361115e57826040518060400160405280601981526020017f68747470733a2f2f756d622e7374616b6572732e776f726c640000000000000081525091509150611829565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111e557826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611829565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361124f5782604051806060016040528060238152602001612c566023913991509150611829565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112d657826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611829565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113405782604051806060016040528060278152602001612cbf6027913991509150611829565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113c757826040518060400160405280601881526020017f68747470733a2f2f756d622e68617368717561726b2e696f000000000000000081525091509150611829565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114315782604051806060016040528060248152602001612c9b6024913991509150611829565b73b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361149b5782604051806060016040528060258152602001612ce66025913991509150611829565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152257826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611829565b73777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361158c5782604051806060016040528060278152602001612d2e6027913991509150611829565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361161357826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611829565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361169a57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611829565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036117045782604051806060016040528060238152602001612d0b6023913991509150611829565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361178b57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611829565b73fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361181257826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612d6e6f64652e636d7431332e6575000081525091509150611829565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806118bd575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061190757507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611951575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061199b575073220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806119e557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a2f575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a7957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ac3575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b0d5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b57575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ba1575073b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611beb57507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c35575073777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c7f5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611cc9575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d135750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d5d575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611da7575073fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff811115611dec57611deb612bf7565b5b604051908082528060200260200182016040528015611e1a5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611e4657611e45612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611ea957611ea8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611f0c57611f0b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611f6f57611f6e612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073220230eda8f50067dd9e4729345dabcce0c6154281600481518110611fd257611fd1612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac8160058151811061203557612034612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a388160068151811061209857612097612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa4719653111816007815181106120fb576120fa612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b8160088151811061215e5761215d612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff27144816009815181106121c1576121c0612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600a8151811061222457612223612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073b9c63a350a04d8bd245d18928a26ee036352ddd881600b8151811061228757612286612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600c815181106122ea576122e9612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073777fba3666fa7747476a34577fccc404b263e09f81600d8151811061234d5761234c612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600e815181106123b0576123af612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600f8151811061241357612412612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd08160108151811061247657612475612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb816011815181106124d9576124d8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073fed95453678920c1b7b3a81f033ca02a272255568160128151811061253c5761253b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6125bc816125a9565b82525050565b60006125ce83836125b3565b60208301905092915050565b6000602082019050919050565b60006125f28261257d565b6125fc8185612588565b935061260783612599565b8060005b8381101561263857815161261f88826125c2565b975061262a836125da565b92505060018101905061260b565b5085935050505092915050565b6000602082019050818103600083015261265f81846125e7565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061269282612667565b9050919050565b6126a281612687565b82525050565b60006020820190506126bd6000830184612699565b92915050565b600080fd5b600080fd5b6126d681612687565b81146126e157600080fd5b50565b6000813590506126f3816126cd565b92915050565b612702816125a9565b811461270d57600080fd5b50565b60008135905061271f816126f9565b92915050565b6000806040838503121561273c5761273b6126c3565b5b600061274a858286016126e4565b925050602061275b85828601612710565b9150509250929050565b60008115159050919050565b61277a81612765565b82525050565b60006020820190506127956000830184612771565b92915050565b6000602082840312156127b1576127b06126c3565b5b60006127bf848285016126e4565b91505092915050565b6000819050919050565b6127db816127c8565b82525050565b60006020820190506127f660008301846127d2565b92915050565b612805816125a9565b82525050565b600060208201905061282060008301846127fc565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261284b5761284a612826565b5b8235905067ffffffffffffffff8111156128685761286761282b565b5b60208301915083602082028301111561288457612883612830565b5b9250929050565b600080602083850312156128a2576128a16126c3565b5b600083013567ffffffffffffffff8111156128c0576128bf6126c8565b5b6128cc85828601612835565b92509250509250929050565b6000806000606084860312156128f1576128f06126c3565b5b60006128ff868287016126e4565b9350506020612910868287016126e4565b925050604061292186828701612710565b9150509250925092565b600060208284031215612941576129406126c3565b5b600061294f84828501612710565b91505092915050565b60008083601f84011261296e5761296d612826565b5b8235905067ffffffffffffffff81111561298b5761298a61282b565b5b6020830191508360018202830111156129a7576129a6612830565b5b9250929050565b6000806000604084860312156129c7576129c66126c3565b5b60006129d5868287016126e4565b935050602084013567ffffffffffffffff8111156129f6576129f56126c8565b5b612a0286828701612958565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b612a4381612687565b82525050565b6000612a558383612a3a565b60208301905092915050565b6000602082019050919050565b6000612a7982612a0e565b612a838185612a19565b9350612a8e83612a2a565b8060005b83811015612abf578151612aa68882612a49565b9750612ab183612a61565b925050600181019050612a92565b5085935050505092915050565b60006020820190508181036000830152612ae68184612a6e565b905092915050565b60008060408385031215612b0557612b046126c3565b5b6000612b13858286016126e4565b9250506020612b24858286016126e4565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612b68578082015181840152602081019050612b4d565b83811115612b77576000848401525b50505050565b6000601f19601f8301169050919050565b6000612b9982612b2e565b612ba38185612b39565b9350612bb3818560208601612b4a565b612bbc81612b7d565b840191505092915050565b6000604082019050612bdc6000830185612699565b8181036020830152612bee8184612b8e565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6170692e76616c696461747269756d2e636c756268747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6d68747470733a2f2f756d626e6f64652e626c6f636b636861696e6c69766572706f6f6c2e636f6da26469706673582212209a1752a9ea487818b8a4d658f151da9487c0cc92638142159bacde7ec2d21f7564736f6c634300080d0033", + "numDeployments": 2, + "solcInputHash": "dc68422c0ad35a4fe46d461b096b9383", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_validatorsCount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"NotSupported\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"minAmountForStake\",\"type\":\"uint256\"}],\"name\":\"LogMinAmountForStake\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"NUMBER_OF_VALIDATORS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ONE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TOTAL_SUPPLY\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_0\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_1\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_10\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_11\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_12\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_13\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_14\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_2\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_3\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_4\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_5\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_6\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_7\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_8\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_9\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_ix\",\"type\":\"uint256\"}],\"name\":\"addresses\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validator\",\"type\":\"address\"}],\"name\":\"balances\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"create\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"exit\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBalances\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"allBalances\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumberOfValidators\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"receiveApproval\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"register\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"remove\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"setMinAmountForStake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"stake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"update\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_id\",\"type\":\"address\"}],\"name\":\"validators\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"location\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_validators\",\"type\":\"address[]\"}],\"name\":\"verifyValidators\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addresses(uint256)\":{\"details\":\"gets validator address for provided index\",\"params\":{\"_ix\":\"index in array of list of all validators wallets\"}},\"balanceOf(address)\":{\"details\":\"to follow ERC20 interface\"},\"exit()\":{\"details\":\"unstake and withdraw all tokens\"},\"getName()\":{\"details\":\"to follow Registrable interface\"},\"getNumberOfValidators()\":{\"returns\":{\"_0\":\"total number of registered validators (with and without balance)\"}},\"register()\":{\"details\":\"to follow Registrable interface\"},\"totalSupply()\":{\"details\":\"to follow ERC20 interface\"},\"unregister()\":{\"details\":\"to follow Registrable interface\"},\"validators(address)\":{\"params\":{\"_id\":\"address of validator\"},\"returns\":{\"id\":\"address of validator\",\"location\":\"URL of validator\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":\"StakingBankStaticProd\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":0},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBank.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IStakingBank is IERC20 {\\n /// @param id address of validator wallet\\n /// @param location URL of the validator API\\n struct Validator {\\n address id;\\n string location;\\n }\\n\\n event LogValidatorRegistered(address indexed id);\\n event LogValidatorUpdated(address indexed id);\\n event LogValidatorRemoved(address indexed id);\\n event LogMinAmountForStake(uint256 minAmountForStake);\\n\\n /// @dev setter for `minAmountForStake`\\n function setMinAmountForStake(uint256 _minAmountForStake) external;\\n\\n /// @dev allows to stake `token` by validators\\n /// Validator needs to approve StakingBank beforehand\\n /// @param _value amount of tokens to stake\\n function stake(uint256 _value) external;\\n\\n /// @dev notification about approval from `_from` address on UMB token\\n /// Staking bank will stake max approved amount from `_from` address\\n /// @param _from address which approved token spend for IStakingBank\\n function receiveApproval(address _from) external returns (bool success);\\n\\n /// @dev withdraws stake tokens\\n /// it throws, when balance will be less than required minimum for stake\\n /// to withdraw all use `exit`\\n function withdraw(uint256 _value) external returns (bool success);\\n\\n /// @dev unstake and withdraw all tokens\\n function exit() external returns (bool success);\\n\\n /// @dev creates (register) new validator\\n /// @param _id validator address\\n /// @param _location location URL of the validator API\\n function create(address _id, string calldata _location) external;\\n\\n /// @dev removes validator\\n /// @param _id validator wallet\\n function remove(address _id) external;\\n\\n /// @dev updates validator location\\n /// @param _id validator wallet\\n /// @param _location new validator URL\\n function update(address _id, string calldata _location) external;\\n\\n /// @return total number of registered validators (with and without balance)\\n function getNumberOfValidators() external view returns (uint256);\\n\\n /// @dev gets validator address for provided index\\n /// @param _ix index in array of list of all validators wallets\\n function addresses(uint256 _ix) external view returns (address);\\n\\n /// @param _id address of validator\\n /// @return id address of validator\\n /// @return location URL of validator\\n function validators(address _id) external view returns (address id, string memory location);\\n}\\n\",\"keccak256\":\"0x2c518aeab8b0b3a364fafaec559d3ff0dc6a119f8d203fa31ef7ad667ca0f7b9\",\"license\":\"MIT\"},\"contracts/interfaces/StakingBankStaticNotSupported.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./IStakingBank.sol\\\";\\n\\nabstract contract StakingBankStaticNotSupported is IStakingBank {\\n error NotSupported();\\n\\n function create(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function update(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function remove(address) external pure {\\n revert NotSupported();\\n }\\n\\n function transfer(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function transferFrom(address, address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function receiveApproval(address) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function allowance(address, address) external pure returns (uint256) {\\n revert NotSupported();\\n }\\n\\n function approve(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function stake(uint256) external pure {\\n revert NotSupported();\\n }\\n\\n function withdraw(uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function exit() external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function setMinAmountForStake(uint256) external pure {\\n revert NotSupported();\\n }\\n}\\n\",\"keccak256\":\"0xa899ad9000220b04bc3f63f762a9a6a76dcc09449427e7774a53f4ceda9c1cf8\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStatic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"../interfaces/StakingBankStaticNotSupported.sol\\\";\\n\\n/// @dev Because we are using PoA in UMB oracle, staked balance does not matter. What's matter is, if signer is\\n/// validator or not. In this case we can optimise `StakingBank` and make it static for better gas performance.\\nabstract contract StakingBankStatic is StakingBankStaticNotSupported {\\n uint256 public constant ONE = 1e18;\\n\\n uint256 public immutable NUMBER_OF_VALIDATORS; // solhint-disable-line var-name-mixedcase\\n uint256 public immutable TOTAL_SUPPLY; // solhint-disable-line var-name-mixedcase\\n\\n constructor(uint256 _validatorsCount) {\\n NUMBER_OF_VALIDATORS = _validatorsCount;\\n TOTAL_SUPPLY = _validatorsCount * ONE;\\n\\n _assertValidSetup(_validatorsCount);\\n }\\n\\n function balances(address _validator) external view returns (uint256) {\\n return _isValidator(_validator) ? ONE : 0;\\n }\\n\\n function verifyValidators(address[] calldata _validators) external view returns (bool) {\\n for (uint256 i; i < _validators.length;) {\\n if (!_isValidator(_validators[i])) return false;\\n unchecked { i++; }\\n }\\n\\n return true;\\n }\\n\\n function getNumberOfValidators() external view returns (uint256) {\\n return NUMBER_OF_VALIDATORS;\\n }\\n\\n function getAddresses() external view returns (address[] memory) {\\n return _addresses();\\n }\\n\\n function getBalances() external view returns (uint256[] memory allBalances) {\\n allBalances = new uint256[](NUMBER_OF_VALIDATORS);\\n\\n for (uint256 i; i < NUMBER_OF_VALIDATORS;) {\\n allBalances[i] = ONE;\\n\\n unchecked {\\n // we will not have enough data to overflow\\n i++;\\n }\\n }\\n }\\n\\n function addresses(uint256 _ix) external view returns (address) {\\n return _addresses()[_ix];\\n }\\n\\n function validators(address _id) external view virtual returns (address id, string memory location);\\n\\n /// @dev to follow ERC20 interface\\n function balanceOf(address _account) external view returns (uint256) {\\n return _isValidator(_account) ? ONE : 0;\\n }\\n\\n /// @dev to follow ERC20 interface\\n function totalSupply() external view returns (uint256) {\\n return TOTAL_SUPPLY;\\n }\\n\\n /// @dev to follow Registrable interface\\n function getName() external pure returns (bytes32) {\\n return \\\"StakingBank\\\";\\n }\\n\\n /// @dev to follow Registrable interface\\n function register() external pure {\\n // there are no requirements atm\\n }\\n\\n /// @dev to follow Registrable interface\\n function unregister() external pure {\\n // there are no requirements atm\\n }\\n\\n function _addresses() internal view virtual returns (address[] memory);\\n\\n function _isValidator(address _validator) internal view virtual returns (bool);\\n\\n function _assertValidSetup(uint256 _validatorsCount) internal view virtual{\\n address[] memory list = _addresses();\\n require(list.length == _validatorsCount);\\n\\n for (uint256 i; i < _validatorsCount;) {\\n require(_isValidator(list[i]));\\n\\n unchecked { i ++; }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfcc53ff98b0f1c42e1bc7345a1535fdc4e938ef40d323600ead94b2ece59a381\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./StakingBankStatic.sol\\\";\\n\\ncontract StakingBankStaticProd is StakingBankStatic {\\n address public constant VALIDATOR_0 = 0x977Ba523420110e230643B772Fe9cF955e11dA7B;\\n address public constant VALIDATOR_1 = 0xe2422b23e52bc13ebA04d7FbB9F332Deb43360fB;\\n\\n // external order is based on validators submits on AVAX for Apr 2023\\n address public constant VALIDATOR_2 = 0x57F404aD75e371c1A539589C1eFCA12e0C6980AD;\\n address public constant VALIDATOR_3 = 0xD56C6A4f64E0bD70260472d1DB6Cf5825858CB0d;\\n address public constant VALIDATOR_4 = 0x93FdcAB283b0BcAc48157590af482E1CFd6af6aC;\\n address public constant VALIDATOR_5 = 0xCd733E06B06083d52fC5867E8E3432aA5c103A38;\\n address public constant VALIDATOR_6 = 0x42e210b110c6aa49CdfA7ceF1444Aa4719653111;\\n address public constant VALIDATOR_7 = 0x501731c6a69803a53Ec6c3e12f293c247cE1092B;\\n address public constant VALIDATOR_8 = 0x8bF9661F1b247522C75DD0FE84355aD2EfF27144;\\n address public constant VALIDATOR_9 = 0x281754Ab58391A478B7aA4E7f39991CfB41118c4;\\n address public constant VALIDATOR_10 = 0x57A51D5BDcE188c2295fCA3b4687475a54E65A02;\\n address public constant VALIDATOR_11 = 0x2F85824B2B38F179E451988670935d315b5b9692;\\n address public constant VALIDATOR_12 = 0xA7241994267682de4dE7Ef62f52dc2C783d1784B;\\n address public constant VALIDATOR_13 = 0x6eEd457C20603EDAE50C3A112CAA1a9425321bD0;\\n address public constant VALIDATOR_14 = 0xC5a7650c2725a7B6A39f15cb9FbffC7af357AFeb;\\n\\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\\n\\n // solhint-disable-next-line code-complexity\\n function validators(address _id) external pure override returns (address id, string memory location) {\\n if (_id == VALIDATOR_0) return (_id, \\\"https://validator.umb.network\\\");\\n if (_id == VALIDATOR_1) return (_id, \\\"https://validator2.umb.network\\\");\\n if (_id == VALIDATOR_2) return (_id, \\\"https://umbrella.artemahr.tech\\\");\\n if (_id == VALIDATOR_3) return (_id, \\\"https://umb.vtabsolutions.com:3030\\\");\\n if (_id == VALIDATOR_4) return (_id, \\\"https://umbrella.crazywhale.es\\\");\\n if (_id == VALIDATOR_5) return (_id, \\\"https://umbrella-node.gateomega.com\\\");\\n if (_id == VALIDATOR_6) return (_id, \\\"https://umb.anorak.technology\\\");\\n if (_id == VALIDATOR_7) return (_id, \\\"https://umbrella.validator.infstones.io\\\");\\n if (_id == VALIDATOR_8) return (_id, \\\"https://umb.hashkey.cloud\\\");\\n if (_id == VALIDATOR_9) return (_id, \\\"http://umbrella.staking4all.org:3000\\\");\\n if (_id == VALIDATOR_10) return (_id, \\\"http://5.161.78.230:3000\\\");\\n if (_id == VALIDATOR_11) return (_id, \\\"https://umb-api.staking.rocks\\\");\\n if (_id == VALIDATOR_12) return (_id, \\\"https://rpc.urbanhq.net\\\");\\n if (_id == VALIDATOR_13) return (_id, \\\"https://umbrella-node.ankastake.com\\\");\\n if (_id == VALIDATOR_14) return (_id, \\\"https://umbrella.tchambrella.com\\\");\\n\\n return (address(0), \\\"\\\");\\n }\\n\\n function _addresses() internal view override returns (address[] memory) {\\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\\n\\n list[0] = VALIDATOR_0;\\n list[1] = VALIDATOR_1;\\n list[2] = VALIDATOR_2;\\n list[3] = VALIDATOR_3;\\n list[4] = VALIDATOR_4;\\n list[5] = VALIDATOR_5;\\n list[6] = VALIDATOR_6;\\n list[7] = VALIDATOR_7;\\n list[8] = VALIDATOR_8;\\n list[9] = VALIDATOR_9;\\n list[10] = VALIDATOR_10;\\n list[11] = VALIDATOR_11;\\n list[12] = VALIDATOR_12;\\n list[13] = VALIDATOR_13;\\n list[14] = VALIDATOR_14;\\n\\n return list;\\n }\\n\\n function _isValidator(address _validator) internal pure override returns (bool) {\\n return (\\n _validator == VALIDATOR_0\\n || _validator == VALIDATOR_1\\n || _validator == VALIDATOR_2\\n || _validator == VALIDATOR_3\\n || _validator == VALIDATOR_4\\n || _validator == VALIDATOR_5\\n || _validator == VALIDATOR_6\\n || _validator == VALIDATOR_7\\n || _validator == VALIDATOR_8\\n || _validator == VALIDATOR_9\\n || _validator == VALIDATOR_10\\n || _validator == VALIDATOR_11\\n || _validator == VALIDATOR_12\\n || _validator == VALIDATOR_13\\n || _validator == VALIDATOR_14\\n );\\n }\\n}\\n\",\"keccak256\":\"0xcf8016c7d7325800fb6ac9f7afd34804b738daded6239139b23f894855a4f98b\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c06040523480156200001157600080fd5b50604051620034f8380380620034f8833981810160405281019062000037919062000beb565b808060808181525050670de0b6b3a76400008162000056919062000c4c565b60a081815250506200006e816200007660201b60201c565b505062000d0b565b600062000088620000ef60201b60201c565b9050818151146200009857600080fd5b60005b82811015620000ea57620000d2828281518110620000be57620000bd62000cad565b5b60200260200101516200074560201b60201c565b620000dc57600080fd5b80806001019150506200009b565b505050565b6060600060805167ffffffffffffffff81111562000112576200011162000cdc565b5b604051908082528060200260200182016040528015620001415781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b8160008151811062000170576200016f62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110620001d657620001d562000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad816002815181106200023c576200023b62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110620002a257620002a162000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac8160048151811062000308576200030762000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a38816005815181106200036e576200036d62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa471965311181600681518110620003d457620003d362000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b816007815181106200043a576200043962000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff2714481600881518110620004a0576200049f62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c48160098151811062000506576200050562000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600a815181106200056c576200056b62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600b81518110620005d257620005d162000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600c8151811062000638576200063762000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081600d815181106200069e576200069d62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81600e8151811062000704576200070362000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480620007d5575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806200082057507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806200086b575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80620008b657507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000901575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806200094c57507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000997575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80620009e25750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a2d575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a7857507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ac35750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b0e575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b595750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ba4575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b600080fd5b6000819050919050565b62000bc58162000bb0565b811462000bd157600080fd5b50565b60008151905062000be58162000bba565b92915050565b60006020828403121562000c045762000c0362000bab565b5b600062000c148482850162000bd4565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600062000c598262000bb0565b915062000c668362000bb0565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161562000ca25762000ca162000c1d565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60805160a0516127a462000d54600039600081816109080152610b72015260008181610777015281816107e501528181610b9801528181610ce901526119a601526127a46000f3fe608060405234801561001057600080fd5b50600436106101ed5760003560e01c8062113e08146101f2578063015f7ed61461021057806303a1e2241461022e578063095ea7b31461024c5780630db18e371461027c57806317d7de7c146102ac57806318160ddd146102ca5780631aa3a008146102e85780631d4f9ce0146102f257806323b872dd1461032257806327e235e31461035257806329092d0e146103825780632e1a7d4d1461039e578063398b056e146103ce578063411ff497146103ec57806345f9f8251461040a57806352b41e351461042857806354755335146104445780635dc4bfd31461046257806369dc7ae41461048057806370a082311461049e578063838e7c3a146104ce578063902d55a5146104ea5780639031d9131461050857806390ff7e2e14610526578063989b6996146105445780639f0e948414610562578063a15ab08d14610580578063a39fac121461059c578063a694fc3a146105ba578063a9059cbb146105d6578063b2119eac14610606578063b49b084214610624578063c2ee3a0814610642578063db73177714610660578063dd62ed3e1461067e578063e2dc7a1a146106ae578063e79a198f146106cc578063e985e008146106d6578063e9fad8ee146106f4578063edf26d9b14610712578063fa52c7d814610742575b600080fd5b6101fa610773565b60405161020791906120ab565b60405180910390f35b610218610844565b604051610225919061210e565b60405180910390f35b61023661085c565b604051610243919061210e565b60405180910390f35b6102666004803603810190610261919061218b565b610874565b60405161027391906121e6565b60405180910390f35b61029660048036038101906102919190612201565b6108a8565b6040516102a391906121e6565b60405180910390f35b6102b46108dc565b6040516102c19190612247565b60405180910390f35b6102d2610904565b6040516102df9190612271565b60405180910390f35b6102f061092c565b005b61030c600480360381019061030791906122f1565b61092e565b60405161031991906121e6565b60405180910390f35b61033c6004803603810190610337919061233e565b610994565b60405161034991906121e6565b60405180910390f35b61036c60048036038101906103679190612201565b6109c8565b6040516103799190612271565b60405180910390f35b61039c60048036038101906103979190612201565b6109ef565b005b6103b860048036038101906103b39190612391565b610a21565b6040516103c591906121e6565b60405180910390f35b6103d6610a55565b6040516103e3919061210e565b60405180910390f35b6103f4610a6d565b604051610401919061210e565b60405180910390f35b610412610a85565b60405161041f919061210e565b60405180910390f35b610442600480360381019061043d9190612391565b610a9d565b005b61044c610acf565b604051610459919061210e565b60405180910390f35b61046a610ae7565b604051610477919061210e565b60405180910390f35b610488610aff565b604051610495919061210e565b60405180910390f35b6104b860048036038101906104b39190612201565b610b17565b6040516104c59190612271565b60405180910390f35b6104e860048036038101906104e39190612414565b610b3e565b005b6104f2610b70565b6040516104ff9190612271565b60405180910390f35b610510610b94565b60405161051d9190612271565b60405180910390f35b61052e610bbc565b60405161053b919061210e565b60405180910390f35b61054c610bd4565b604051610559919061210e565b60405180910390f35b61056a610bec565b604051610577919061210e565b60405180910390f35b61059a60048036038101906105959190612414565b610c04565b005b6105a4610c36565b6040516105b19190612532565b60405180910390f35b6105d460048036038101906105cf9190612391565b610c45565b005b6105f060048036038101906105eb919061218b565b610c77565b6040516105fd91906121e6565b60405180910390f35b61060e610cab565b60405161061b919061210e565b60405180910390f35b61062c610cc3565b604051610639919061210e565b60405180910390f35b61064a610cdb565b6040516106579190612271565b60405180910390f35b610668610ce7565b6040516106759190612271565b60405180910390f35b61069860048036038101906106939190612554565b610d0b565b6040516106a59190612271565b60405180910390f35b6106b6610d3f565b6040516106c3919061210e565b60405180910390f35b6106d4610d57565b005b6106de610d59565b6040516106eb919061210e565b60405180910390f35b6106fc610d71565b60405161070991906121e6565b60405180910390f35b61072c60048036038101906107279190612391565b610da5565b604051610739919061210e565b60405180910390f35b61075c60048036038101906107579190612201565b610dd0565b60405161076a92919061262d565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156107af576107ae61265d565b5b6040519080825280602002602001820160405280156107dd5781602001602082028036833780820191505090505b50905060005b7f000000000000000000000000000000000000000000000000000000000000000081101561084057670de0b6b3a76400008282815181106108275761082661268c565b5b60200260200101818152505080806001019150506107e3565b5090565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b838390508110156109885761096d8484838181106109535761095261268c565b5b90506020020160208101906109689190612201565b611548565b61097b57600091505061098e565b8080600101915050610932565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006109d382611548565b6109de5760006109e8565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73a7241994267682de4de7ef62f52dc2c783d1784b81565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b736eed457c20603edae50c3a112caa1a9425321bd081565b6000610b2282611548565b610b2d576000610b37565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73281754ab58391a478b7aa4e7f39991cfb41118c481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610c406119a0565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b565b732f85824b2b38f179e451988670935d315b5b969281565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610daf6119a0565b8281518110610dc157610dc061268c565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e5b57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611543565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610ee257826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611543565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f6957826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611543565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fd357826040518060600160405280602281526020016126df6022913991509150611543565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361105a57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611543565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110c457826040518060600160405280602381526020016126bc6023913991509150611543565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361114b57826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611543565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111b557826040518060600160405280602781526020016127256027913991509150611543565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361123c57826040518060400160405280601981526020017f68747470733a2f2f756d622e686173686b65792e636c6f75640000000000000081525091509150611543565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112a657826040518060600160405280602481526020016127016024913991509150611543565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361132d57826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611543565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113b457826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611543565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361143b57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611543565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114a5578260405180606001604052806023815260200161274c6023913991509150611543565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152c57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611543565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806115d7575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061162157507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061166b575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116b557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116ff575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061174957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611793575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806117dd5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611827575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061187157507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806118bb5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611905575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061194f5750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611999575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156119de576119dd61265d565b5b604051908082528060200260200182016040528015611a0c5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611a3857611a3761268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611a9b57611a9a61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611afe57611afd61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611b6157611b6061268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac81600481518110611bc457611bc361268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a3881600581518110611c2757611c2661268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa471965311181600681518110611c8a57611c8961268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b81600781518110611ced57611cec61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff2714481600881518110611d5057611d4f61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600981518110611db357611db261268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600a81518110611e1657611e1561268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600b81518110611e7957611e7861268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600c81518110611edc57611edb61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081600d81518110611f3f57611f3e61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81600e81518110611fa257611fa161268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6120228161200f565b82525050565b60006120348383612019565b60208301905092915050565b6000602082019050919050565b600061205882611fe3565b6120628185611fee565b935061206d83611fff565b8060005b8381101561209e5781516120858882612028565b975061209083612040565b925050600181019050612071565b5085935050505092915050565b600060208201905081810360008301526120c5818461204d565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006120f8826120cd565b9050919050565b612108816120ed565b82525050565b600060208201905061212360008301846120ff565b92915050565b600080fd5b600080fd5b61213c816120ed565b811461214757600080fd5b50565b60008135905061215981612133565b92915050565b6121688161200f565b811461217357600080fd5b50565b6000813590506121858161215f565b92915050565b600080604083850312156121a2576121a1612129565b5b60006121b08582860161214a565b92505060206121c185828601612176565b9150509250929050565b60008115159050919050565b6121e0816121cb565b82525050565b60006020820190506121fb60008301846121d7565b92915050565b60006020828403121561221757612216612129565b5b60006122258482850161214a565b91505092915050565b6000819050919050565b6122418161222e565b82525050565b600060208201905061225c6000830184612238565b92915050565b61226b8161200f565b82525050565b60006020820190506122866000830184612262565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126122b1576122b061228c565b5b8235905067ffffffffffffffff8111156122ce576122cd612291565b5b6020830191508360208202830111156122ea576122e9612296565b5b9250929050565b6000806020838503121561230857612307612129565b5b600083013567ffffffffffffffff8111156123265761232561212e565b5b6123328582860161229b565b92509250509250929050565b60008060006060848603121561235757612356612129565b5b60006123658682870161214a565b93505060206123768682870161214a565b925050604061238786828701612176565b9150509250925092565b6000602082840312156123a7576123a6612129565b5b60006123b584828501612176565b91505092915050565b60008083601f8401126123d4576123d361228c565b5b8235905067ffffffffffffffff8111156123f1576123f0612291565b5b60208301915083600182028301111561240d5761240c612296565b5b9250929050565b60008060006040848603121561242d5761242c612129565b5b600061243b8682870161214a565b935050602084013567ffffffffffffffff81111561245c5761245b61212e565b5b612468868287016123be565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6124a9816120ed565b82525050565b60006124bb83836124a0565b60208301905092915050565b6000602082019050919050565b60006124df82612474565b6124e9818561247f565b93506124f483612490565b8060005b8381101561252557815161250c88826124af565b9750612517836124c7565b9250506001810190506124f8565b5085935050505092915050565b6000602082019050818103600083015261254c81846124d4565b905092915050565b6000806040838503121561256b5761256a612129565b5b60006125798582860161214a565b925050602061258a8582860161214a565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156125ce5780820151818401526020810190506125b3565b838111156125dd576000848401525b50505050565b6000601f19601f8301169050919050565b60006125ff82612594565b612609818561259f565b93506126198185602086016125b0565b612622816125e3565b840191505092915050565b600060408201905061264260008301856120ff565b818103602083015261265481846125f4565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6da2646970667358221220b875faa4ff94a6ed380db1c82cfc4fcfdce28d00988b3f85c113e0332affbaa264736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101ed5760003560e01c8062113e08146101f2578063015f7ed61461021057806303a1e2241461022e578063095ea7b31461024c5780630db18e371461027c57806317d7de7c146102ac57806318160ddd146102ca5780631aa3a008146102e85780631d4f9ce0146102f257806323b872dd1461032257806327e235e31461035257806329092d0e146103825780632e1a7d4d1461039e578063398b056e146103ce578063411ff497146103ec57806345f9f8251461040a57806352b41e351461042857806354755335146104445780635dc4bfd31461046257806369dc7ae41461048057806370a082311461049e578063838e7c3a146104ce578063902d55a5146104ea5780639031d9131461050857806390ff7e2e14610526578063989b6996146105445780639f0e948414610562578063a15ab08d14610580578063a39fac121461059c578063a694fc3a146105ba578063a9059cbb146105d6578063b2119eac14610606578063b49b084214610624578063c2ee3a0814610642578063db73177714610660578063dd62ed3e1461067e578063e2dc7a1a146106ae578063e79a198f146106cc578063e985e008146106d6578063e9fad8ee146106f4578063edf26d9b14610712578063fa52c7d814610742575b600080fd5b6101fa610773565b60405161020791906120ab565b60405180910390f35b610218610844565b604051610225919061210e565b60405180910390f35b61023661085c565b604051610243919061210e565b60405180910390f35b6102666004803603810190610261919061218b565b610874565b60405161027391906121e6565b60405180910390f35b61029660048036038101906102919190612201565b6108a8565b6040516102a391906121e6565b60405180910390f35b6102b46108dc565b6040516102c19190612247565b60405180910390f35b6102d2610904565b6040516102df9190612271565b60405180910390f35b6102f061092c565b005b61030c600480360381019061030791906122f1565b61092e565b60405161031991906121e6565b60405180910390f35b61033c6004803603810190610337919061233e565b610994565b60405161034991906121e6565b60405180910390f35b61036c60048036038101906103679190612201565b6109c8565b6040516103799190612271565b60405180910390f35b61039c60048036038101906103979190612201565b6109ef565b005b6103b860048036038101906103b39190612391565b610a21565b6040516103c591906121e6565b60405180910390f35b6103d6610a55565b6040516103e3919061210e565b60405180910390f35b6103f4610a6d565b604051610401919061210e565b60405180910390f35b610412610a85565b60405161041f919061210e565b60405180910390f35b610442600480360381019061043d9190612391565b610a9d565b005b61044c610acf565b604051610459919061210e565b60405180910390f35b61046a610ae7565b604051610477919061210e565b60405180910390f35b610488610aff565b604051610495919061210e565b60405180910390f35b6104b860048036038101906104b39190612201565b610b17565b6040516104c59190612271565b60405180910390f35b6104e860048036038101906104e39190612414565b610b3e565b005b6104f2610b70565b6040516104ff9190612271565b60405180910390f35b610510610b94565b60405161051d9190612271565b60405180910390f35b61052e610bbc565b60405161053b919061210e565b60405180910390f35b61054c610bd4565b604051610559919061210e565b60405180910390f35b61056a610bec565b604051610577919061210e565b60405180910390f35b61059a60048036038101906105959190612414565b610c04565b005b6105a4610c36565b6040516105b19190612532565b60405180910390f35b6105d460048036038101906105cf9190612391565b610c45565b005b6105f060048036038101906105eb919061218b565b610c77565b6040516105fd91906121e6565b60405180910390f35b61060e610cab565b60405161061b919061210e565b60405180910390f35b61062c610cc3565b604051610639919061210e565b60405180910390f35b61064a610cdb565b6040516106579190612271565b60405180910390f35b610668610ce7565b6040516106759190612271565b60405180910390f35b61069860048036038101906106939190612554565b610d0b565b6040516106a59190612271565b60405180910390f35b6106b6610d3f565b6040516106c3919061210e565b60405180910390f35b6106d4610d57565b005b6106de610d59565b6040516106eb919061210e565b60405180910390f35b6106fc610d71565b60405161070991906121e6565b60405180910390f35b61072c60048036038101906107279190612391565b610da5565b604051610739919061210e565b60405180910390f35b61075c60048036038101906107579190612201565b610dd0565b60405161076a92919061262d565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156107af576107ae61265d565b5b6040519080825280602002602001820160405280156107dd5781602001602082028036833780820191505090505b50905060005b7f000000000000000000000000000000000000000000000000000000000000000081101561084057670de0b6b3a76400008282815181106108275761082661268c565b5b60200260200101818152505080806001019150506107e3565b5090565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b838390508110156109885761096d8484838181106109535761095261268c565b5b90506020020160208101906109689190612201565b611548565b61097b57600091505061098e565b8080600101915050610932565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006109d382611548565b6109de5760006109e8565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73a7241994267682de4de7ef62f52dc2c783d1784b81565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b736eed457c20603edae50c3a112caa1a9425321bd081565b6000610b2282611548565b610b2d576000610b37565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73281754ab58391a478b7aa4e7f39991cfb41118c481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610c406119a0565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b565b732f85824b2b38f179e451988670935d315b5b969281565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610daf6119a0565b8281518110610dc157610dc061268c565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e5b57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611543565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610ee257826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611543565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f6957826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611543565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fd357826040518060600160405280602281526020016126df6022913991509150611543565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361105a57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611543565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110c457826040518060600160405280602381526020016126bc6023913991509150611543565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361114b57826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611543565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111b557826040518060600160405280602781526020016127256027913991509150611543565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361123c57826040518060400160405280601981526020017f68747470733a2f2f756d622e686173686b65792e636c6f75640000000000000081525091509150611543565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112a657826040518060600160405280602481526020016127016024913991509150611543565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361132d57826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611543565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113b457826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611543565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361143b57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611543565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114a5578260405180606001604052806023815260200161274c6023913991509150611543565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152c57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611543565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806115d7575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061162157507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061166b575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116b557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116ff575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061174957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611793575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806117dd5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611827575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061187157507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806118bb5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611905575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061194f5750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611999575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156119de576119dd61265d565b5b604051908082528060200260200182016040528015611a0c5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611a3857611a3761268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611a9b57611a9a61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611afe57611afd61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611b6157611b6061268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac81600481518110611bc457611bc361268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a3881600581518110611c2757611c2661268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa471965311181600681518110611c8a57611c8961268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b81600781518110611ced57611cec61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff2714481600881518110611d5057611d4f61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600981518110611db357611db261268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600a81518110611e1657611e1561268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600b81518110611e7957611e7861268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600c81518110611edc57611edb61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081600d81518110611f3f57611f3e61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81600e81518110611fa257611fa161268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6120228161200f565b82525050565b60006120348383612019565b60208301905092915050565b6000602082019050919050565b600061205882611fe3565b6120628185611fee565b935061206d83611fff565b8060005b8381101561209e5781516120858882612028565b975061209083612040565b925050600181019050612071565b5085935050505092915050565b600060208201905081810360008301526120c5818461204d565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006120f8826120cd565b9050919050565b612108816120ed565b82525050565b600060208201905061212360008301846120ff565b92915050565b600080fd5b600080fd5b61213c816120ed565b811461214757600080fd5b50565b60008135905061215981612133565b92915050565b6121688161200f565b811461217357600080fd5b50565b6000813590506121858161215f565b92915050565b600080604083850312156121a2576121a1612129565b5b60006121b08582860161214a565b92505060206121c185828601612176565b9150509250929050565b60008115159050919050565b6121e0816121cb565b82525050565b60006020820190506121fb60008301846121d7565b92915050565b60006020828403121561221757612216612129565b5b60006122258482850161214a565b91505092915050565b6000819050919050565b6122418161222e565b82525050565b600060208201905061225c6000830184612238565b92915050565b61226b8161200f565b82525050565b60006020820190506122866000830184612262565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126122b1576122b061228c565b5b8235905067ffffffffffffffff8111156122ce576122cd612291565b5b6020830191508360208202830111156122ea576122e9612296565b5b9250929050565b6000806020838503121561230857612307612129565b5b600083013567ffffffffffffffff8111156123265761232561212e565b5b6123328582860161229b565b92509250509250929050565b60008060006060848603121561235757612356612129565b5b60006123658682870161214a565b93505060206123768682870161214a565b925050604061238786828701612176565b9150509250925092565b6000602082840312156123a7576123a6612129565b5b60006123b584828501612176565b91505092915050565b60008083601f8401126123d4576123d361228c565b5b8235905067ffffffffffffffff8111156123f1576123f0612291565b5b60208301915083600182028301111561240d5761240c612296565b5b9250929050565b60008060006040848603121561242d5761242c612129565b5b600061243b8682870161214a565b935050602084013567ffffffffffffffff81111561245c5761245b61212e565b5b612468868287016123be565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6124a9816120ed565b82525050565b60006124bb83836124a0565b60208301905092915050565b6000602082019050919050565b60006124df82612474565b6124e9818561247f565b93506124f483612490565b8060005b8381101561252557815161250c88826124af565b9750612517836124c7565b9250506001810190506124f8565b5085935050505092915050565b6000602082019050818103600083015261254c81846124d4565b905092915050565b6000806040838503121561256b5761256a612129565b5b60006125798582860161214a565b925050602061258a8582860161214a565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156125ce5780820151818401526020810190506125b3565b838111156125dd576000848401525b50505050565b6000601f19601f8301169050919050565b60006125ff82612594565b612609818561259f565b93506126198185602086016125b0565b612622816125e3565b840191505092915050565b600060408201905061264260008301856120ff565b818103602083015261265481846125f4565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6da2646970667358221220b875faa4ff94a6ed380db1c82cfc4fcfdce28d00988b3f85c113e0332affbaa264736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/bob_production/UmbrellaFeeds.json b/deployments/bob_production/UmbrellaFeeds.json index a3357c55..b7ab61b2 100644 --- a/deployments/bob_production/UmbrellaFeeds.json +++ b/deployments/bob_production/UmbrellaFeeds.json @@ -1,5 +1,5 @@ { - "address": "0xDa9A63D77406faa09d265413F4E128B54b5057e0", + "address": "0x9AeC6E90CA8ba83571deb13C2ac90Be95F054aBd", "abi": [ { "inputs": [ @@ -662,19 +662,19 @@ "type": "function" } ], - "transactionHash": "0xe65ba6606dffe6e4d22ca5451013e12037eae35a6d43e03636f11f19cd93cb03", + "transactionHash": "0xed126197b7e4395e3b9dcbc1870aa6db6784337153fb0841c1f9dee88ab9babe", "receipt": { "to": null, "from": "0xA6e4fFa19B213AbeA258ae72e8e1a209B9E543e7", - "contractAddress": "0xDa9A63D77406faa09d265413F4E128B54b5057e0", + "contractAddress": "0x9AeC6E90CA8ba83571deb13C2ac90Be95F054aBd", "transactionIndex": 1, "gasUsed": "2534549", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x53b773f394fa56a6816cbfbd06d62a7935bb6bd016f2ade9743e0d2e63298f99", - "transactionHash": "0xe65ba6606dffe6e4d22ca5451013e12037eae35a6d43e03636f11f19cd93cb03", + "blockHash": "0xaf6aeaff266115b9e7cf98091d35b434ec8e6ddab116dd875c788d870513ab54", + "transactionHash": "0xed126197b7e4395e3b9dcbc1870aa6db6784337153fb0841c1f9dee88ab9babe", "logs": [], - "blockNumber": 7475708, - "cumulativeGasUsed": "2578412", + "blockNumber": 8710319, + "cumulativeGasUsed": "2578436", "status": 1, "byzantium": true }, @@ -684,7 +684,7 @@ 8 ], "numDeployments": 1, - "solcInputHash": "c45d125781228a2640f2fc0eee67ec9d", + "solcInputHash": "dc68422c0ad35a4fe46d461b096b9383", "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"_contractRegistry\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"_requiredSignatures\",\"type\":\"uint16\"},{\"internalType\":\"uint8\",\"name\":\"_decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ArraysDataDoNotMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractInUse\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractNotInitialised\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ECDSAInvalidSignatureS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ECDSAInvalidSignatureV\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FeedNotExist\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRequiredSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotEnoughSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OldData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfOrder\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DECIMALS\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DEPLOYED_AT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ETH_PREFIX\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NAME\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REGISTRY\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REQUIRED_SIGNATURES\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"STAKING_BANK\",\"outputs\":[{\"internalType\":\"contract IStakingBankStatic\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"destroy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_keys\",\"type\":\"bytes32[]\"}],\"name\":\"getManyPriceData\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData[]\",\"name\":\"data\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_keys\",\"type\":\"bytes32[]\"}],\"name\":\"getManyPriceDataRaw\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData[]\",\"name\":\"data\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getPrice\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getPriceData\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData\",\"name\":\"data\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"getPriceDataByName\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData\",\"name\":\"data\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getPriceTimestamp\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getPriceTimestampHeartbeat\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_priceKeys\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData[]\",\"name\":\"_priceDatas\",\"type\":\"tuple[]\"}],\"name\":\"hashData\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"prices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData\",\"name\":\"data\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_hash\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"_v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"_r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_s\",\"type\":\"bytes32\"}],\"name\":\"recoverSigner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_priceKeys\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData[]\",\"name\":\"_priceDatas\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"struct IUmbrellaFeeds.Signature[]\",\"name\":\"_signatures\",\"type\":\"tuple[]\"}],\"name\":\"update\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_hash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"struct IUmbrellaFeeds.Signature[]\",\"name\":\"_signatures\",\"type\":\"tuple[]\"}],\"name\":\"verifySignatures\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Main contract for all on-chain data. Check `UmbrellaFeedsReader` to see how to integrate.\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_contractRegistry\":\"Registry address\",\"_decimals\":\"decimals for prices stored in this contract\",\"_requiredSignatures\":\"number of required signatures for accepting consensus submission\"}},\"destroy(string)\":{\"details\":\"destroys old contract there is sanity check that prevents abuse of destroy method\",\"params\":{\"_name\":\"string feed key to verify, that contract was initialised\"}},\"getManyPriceData(bytes32[])\":{\"details\":\"it will return array of price datas for provided `_keys` In case ony of feed does not exist, fallback call will be executed for that feed.\",\"params\":{\"_keys\":\"array of feed keys\"},\"returns\":{\"data\":\"PriceData array\"}},\"getManyPriceDataRaw(bytes32[])\":{\"details\":\"same as getManyPriceData() but does not revert on empty data.\"},\"getName()\":{\"details\":\"to follow Registrable interface\"},\"getPrice(bytes32)\":{\"params\":{\"_key\":\"hash of feed name\"},\"returns\":{\"price\":\"price\"}},\"getPriceData(bytes32)\":{\"details\":\"this is main endpoint for reading feeds. In case timestamp is empty (that means there is no data), contract will revert. If you do not need whole data from `PriceData` struct, you can save some gas by using other view methods that returns just what you need.\",\"params\":{\"_key\":\"hash of feed name\"},\"returns\":{\"data\":\"full PriceData struct\"}},\"getPriceDataByName(string)\":{\"details\":\"This method should be used only for Layer2 as it is more gas consuming than others views.\",\"params\":{\"_name\":\"string feed name\"},\"returns\":{\"data\":\"PriceData\"}},\"getPriceTimestamp(bytes32)\":{\"params\":{\"_key\":\"hash of feed name\"},\"returns\":{\"price\":\"price\",\"timestamp\":\"timestamp\"}},\"getPriceTimestampHeartbeat(bytes32)\":{\"params\":{\"_key\":\"hash of feed name\"},\"returns\":{\"heartbeat\":\"heartbeat\",\"price\":\"price\",\"timestamp\":\"timestamp\"}},\"hashData(bytes32[],(uint8,uint24,uint32,uint128)[])\":{\"details\":\"helper method for QA purposes\",\"returns\":{\"_0\":\"hash of data that are signed by validators (keys and priced data)\"}},\"prices(bytes32)\":{\"params\":{\"_key\":\"hash of feed name\"},\"returns\":{\"data\":\"full PriceData struct\"}},\"recoverSigner(bytes32,uint8,bytes32,bytes32)\":{\"params\":{\"_hash\":\"hashed of data\",\"_r\":\"part of signature\",\"_s\":\"part of signature\",\"_v\":\"part of signature\"},\"returns\":{\"_0\":\"signer address\"}},\"update(bytes32[],(uint8,uint24,uint32,uint128)[],(uint8,bytes32,bytes32)[])\":{\"details\":\"method for submitting consensus data\",\"params\":{\"_priceDatas\":\"PriceData signed by validators\",\"_priceKeys\":\"array of keys for `_priceDatas`\",\"_signatures\":\"validators signatures\"}},\"verifySignatures(bytes32,(uint8,bytes32,bytes32)[])\":{\"params\":{\"_hash\":\"hash of signed data\",\"_signatures\":\"array of validators signatures\"}}},\"stateVariables\":{\"DECIMALS\":{\"details\":\"decimals for prices stored in this contract\"},\"DEPLOYED_AT\":{\"details\":\"deployment time, used for protect for unintentional destroy\"},\"REGISTRY\":{\"details\":\"Registry contract where list of all addresses is stored. Fallback feature uses this registry to resolve newest `UmbrellaFeeds` address\"},\"REQUIRED_SIGNATURES\":{\"details\":\"minimal number of signatures required for accepting price submission (PoA)\"},\"STAKING_BANK\":{\"details\":\"StakingBank contract where list of validators is stored\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getManyPriceData(bytes32[])\":{\"notice\":\"If data for any key not exists, function will revert. Use `getManyPriceDataRaw` method if you don't want revert.\"},\"getManyPriceDataRaw(bytes32[])\":{\"notice\":\"This method does no revert if some data does not exists. Check `data.timestamp` to see if price exist, if it is 0, then it does not exist.\"},\"getPrice(bytes32)\":{\"notice\":\"method will revert if data for `_key` not exists.\"},\"getPriceData(bytes32)\":{\"notice\":\"method will revert if data for `_key` not exists.\"},\"getPriceDataByName(string)\":{\"notice\":\"It does not revert on empty data.\"},\"getPriceTimestamp(bytes32)\":{\"notice\":\"method will revert if data for `_key` not exists.\"},\"getPriceTimestampHeartbeat(bytes32)\":{\"notice\":\"method will revert if data for `_key` not exists.\"},\"prices(bytes32)\":{\"notice\":\"reader for mapping\"}},\"notice\":\"This contract can be destroyed and replaced with new one (with new address). For best gas efficiency you should pick one of two ways of integration: 1. make `UmbrellaFeeds` immutable and use fallback in case of selfdestruct. After new deployment, it is recommended to update address to avoid fallback and reduce gas cost to minimum. In long run this is most efficient solution, better than any proxy. 2. always check newest `UmbrellaFeeds` via `Regostry` and fallback will not be needed.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/onChainFeeds/UmbrellaFeeds.sol\":\"UmbrellaFeeds\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":0},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/interfaces/IRegistry.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\n\\ninterface IRegistry {\\n event LogRegistered(address indexed destination, bytes32 name);\\n\\n /// @dev imports new contract addresses and override old addresses, if they exist under provided name\\n /// This method can be used for contracts that for some reason do not have `getName` method\\n /// @param _names array of contract names that we want to register\\n /// @param _destinations array of contract addresses\\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external;\\n\\n /// @dev imports new contracts and override old addresses, if they exist.\\n /// Names of contracts are fetched directly from each contract by calling `getName`\\n /// @param _destinations array of contract addresses\\n function importContracts(address[] calldata _destinations) external;\\n\\n /// @dev this method ensure, that old and new contract is aware of it state in registry\\n /// Note: BSC registry does not have this method. This method was introduced in later stage.\\n /// @param _newContract address of contract that will replace old one\\n function atomicUpdate(address _newContract) external;\\n\\n /// @dev similar to `getAddress` but throws when contract name not exists\\n /// @param name contract name\\n /// @return contract address registered under provided name or throws, if does not exists\\n function requireAndGetAddress(bytes32 name) external view returns (address);\\n\\n /// @param name contract name in a form of bytes32\\n /// @return contract address registered under provided name\\n function getAddress(bytes32 name) external view returns (address);\\n\\n /// @param _name contract name\\n /// @return contract address assigned to the name or address(0) if not exists\\n function getAddressByString(string memory _name) external view returns (address);\\n\\n /// @dev helper method that converts string to bytes32,\\n /// you can use to to generate contract name\\n function stringToBytes32(string memory _string) external pure returns (bytes32 result);\\n}\\n\",\"keccak256\":\"0xa0099ecf4182138fda7a0733407784461410c245de67c1e7ba7cd7c9595e054f\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBank.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IStakingBank is IERC20 {\\n /// @param id address of validator wallet\\n /// @param location URL of the validator API\\n struct Validator {\\n address id;\\n string location;\\n }\\n\\n event LogValidatorRegistered(address indexed id);\\n event LogValidatorUpdated(address indexed id);\\n event LogValidatorRemoved(address indexed id);\\n event LogMinAmountForStake(uint256 minAmountForStake);\\n\\n /// @dev setter for `minAmountForStake`\\n function setMinAmountForStake(uint256 _minAmountForStake) external;\\n\\n /// @dev allows to stake `token` by validators\\n /// Validator needs to approve StakingBank beforehand\\n /// @param _value amount of tokens to stake\\n function stake(uint256 _value) external;\\n\\n /// @dev notification about approval from `_from` address on UMB token\\n /// Staking bank will stake max approved amount from `_from` address\\n /// @param _from address which approved token spend for IStakingBank\\n function receiveApproval(address _from) external returns (bool success);\\n\\n /// @dev withdraws stake tokens\\n /// it throws, when balance will be less than required minimum for stake\\n /// to withdraw all use `exit`\\n function withdraw(uint256 _value) external returns (bool success);\\n\\n /// @dev unstake and withdraw all tokens\\n function exit() external returns (bool success);\\n\\n /// @dev creates (register) new validator\\n /// @param _id validator address\\n /// @param _location location URL of the validator API\\n function create(address _id, string calldata _location) external;\\n\\n /// @dev removes validator\\n /// @param _id validator wallet\\n function remove(address _id) external;\\n\\n /// @dev updates validator location\\n /// @param _id validator wallet\\n /// @param _location new validator URL\\n function update(address _id, string calldata _location) external;\\n\\n /// @return total number of registered validators (with and without balance)\\n function getNumberOfValidators() external view returns (uint256);\\n\\n /// @dev gets validator address for provided index\\n /// @param _ix index in array of list of all validators wallets\\n function addresses(uint256 _ix) external view returns (address);\\n\\n /// @param _id address of validator\\n /// @return id address of validator\\n /// @return location URL of validator\\n function validators(address _id) external view returns (address id, string memory location);\\n}\\n\",\"keccak256\":\"0x2c518aeab8b0b3a364fafaec559d3ff0dc6a119f8d203fa31ef7ad667ca0f7b9\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBankStatic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./IStakingBank.sol\\\";\\n\\n\\ninterface IStakingBankStatic is IStakingBank {\\n /// @param _validators array of validators addresses to verify\\n /// @return TRUE when all validators are valid, FALSE otherwise\\n function verifyValidators(address[] calldata _validators) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xb7829f090205357ae8c7b86490504897060650c149309362b95eacbeef88d8ba\",\"license\":\"MIT\"},\"contracts/interfaces/IUmbrellaFeeds.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IUmbrellaFeeds {\\n struct PriceData {\\n /// @dev this is placeholder, that can be used for some additional data\\n /// atm of creating this smart contract, it is only used as marker for removed data (when == type(uint8).max)\\n uint8 data;\\n /// @dev heartbeat: how often price data will be refreshed in case price stay flat\\n uint24 heartbeat;\\n /// @dev timestamp: price time, at this time validators run consensus\\n uint32 timestamp;\\n /// @dev price\\n uint128 price;\\n }\\n\\n struct Signature {\\n uint8 v;\\n bytes32 r;\\n bytes32 s;\\n }\\n\\n /// @dev method for submitting consensus data\\n /// @param _priceKeys array of keys for `_priceDatas`\\n /// @param _priceDatas PriceData signed by validators\\n /// @param _signatures validators signatures\\n function update(\\n bytes32[] calldata _priceKeys,\\n PriceData[] calldata _priceDatas,\\n Signature[] calldata _signatures\\n ) external;\\n\\n /// @dev it will return array of price datas for provided `_keys`\\n /// In case ony of feed does not exist, fallback call will be executed for that feed.\\n /// @notice If data for any key not exists, function will revert. Use `getManyPriceDataRaw` method if you don't\\n /// want revert.\\n /// @param _keys array of feed keys\\n /// @return data PriceData array\\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data);\\n\\n /// @dev same as getManyPriceData() but does not revert on empty data.\\n /// @notice This method does no revert if some data does not exists.\\n /// Check `data.timestamp` to see if price exist, if it is 0, then it does not exist.\\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data);\\n\\n /// @dev this is main endpoint for reading feeds.\\n /// In case timestamp is empty (that means there is no data), contract will revert.\\n /// If you do not need whole data from `PriceData` struct, you can save some gas by using other view methods that\\n /// returns just what you need.\\n /// @notice method will revert if data for `_key` not exists.\\n /// @param _key hash of feed name\\n /// @return data full PriceData struct\\n function getPriceData(bytes32 _key) external view returns (PriceData memory data);\\n\\n /// @notice reader for mapping\\n /// @param _key hash of feed name\\n /// @return data full PriceData struct\\n function prices(bytes32 _key) external view returns (PriceData memory data);\\n\\n /// @notice method will revert if data for `_key` not exists.\\n /// @param _key hash of feed name\\n /// @return price\\n function getPrice(bytes32 _key) external view returns (uint128 price);\\n\\n /// @notice method will revert if data for `_key` not exists.\\n /// @param _key hash of feed name\\n /// @return price\\n /// @return timestamp\\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp);\\n\\n /// @notice method will revert if data for `_key` not exists.\\n /// @param _key hash of feed name\\n /// @return price\\n /// @return timestamp\\n /// @return heartbeat\\n function getPriceTimestampHeartbeat(bytes32 _key)\\n external\\n view\\n returns (uint128 price, uint32 timestamp, uint24 heartbeat);\\n\\n /// @dev This method should be used only for Layer2 as it is more gas consuming than others views.\\n /// @notice It does not revert on empty data.\\n /// @param _name string feed name\\n /// @return data PriceData\\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data);\\n\\n /// @dev decimals for prices stored in this contract\\n function DECIMALS() external view returns (uint8); // solhint-disable-line func-name-mixedcase\\n}\\n\",\"keccak256\":\"0x3b89742a9ab465f00aa9cf8635a5dfdc02d7ecf9bad8f564bee7c15d8aea46cb\",\"license\":\"MIT\"},\"contracts/onChainFeeds/UmbrellaFeeds.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"../interfaces/IUmbrellaFeeds.sol\\\";\\nimport \\\"../interfaces/IRegistry.sol\\\";\\nimport \\\"../interfaces/IStakingBankStatic.sol\\\";\\n\\n/// @dev Main contract for all on-chain data.\\n/// Check `UmbrellaFeedsReader` to see how to integrate.\\n///\\n/// @notice This contract can be destroyed and replaced with new one (with new address).\\n/// For best gas efficiency you should pick one of two ways of integration:\\n/// 1. make `UmbrellaFeeds` immutable and use fallback in case of selfdestruct. After new deployment, it is recommended\\n/// to update address to avoid fallback and reduce gas cost to minimum. In long run this is most efficient solution,\\n/// better than any proxy.\\n/// 2. always check newest `UmbrellaFeeds` via `Regostry` and fallback will not be needed.\\ncontract UmbrellaFeeds is IUmbrellaFeeds {\\n bytes constant public ETH_PREFIX = \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\";\\n string constant public NAME = \\\"UmbrellaFeeds\\\";\\n\\n /// @dev deployment time, used for protect for unintentional destroy\\n uint256 public immutable DEPLOYED_AT; // solhint-disable-line var-name-mixedcase\\n\\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\\n /// resolve newest `UmbrellaFeeds` address\\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\\n\\n /// @dev StakingBank contract where list of validators is stored\\n IStakingBankStatic public immutable STAKING_BANK; // solhint-disable-line var-name-mixedcase\\n\\n /// @dev minimal number of signatures required for accepting price submission (PoA)\\n uint16 public immutable REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\\n\\n /// @dev decimals for prices stored in this contract\\n uint8 public immutable DECIMALS; // solhint-disable-line var-name-mixedcase\\n\\n /// @notice map of all prices stored in this contract, key for map is hash of feed name\\n /// eg for \\\"ETH-USD\\\" feed, key will be hash(\\\"ETH-USD\\\")\\n mapping (bytes32 => PriceData) private _prices;\\n\\n error ArraysDataDoNotMatch();\\n error FeedNotExist();\\n error NotEnoughSignatures();\\n error InvalidSigner();\\n error InvalidRequiredSignatures();\\n error SignaturesOutOfOrder();\\n error ECDSAInvalidSignatureS();\\n error ECDSAInvalidSignatureV();\\n error OldData();\\n error ContractInUse();\\n error ContractNotInitialised();\\n\\n /// @param _contractRegistry Registry address\\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\\n /// @param _decimals decimals for prices stored in this contract\\n constructor(\\n IRegistry _contractRegistry,\\n uint16 _requiredSignatures,\\n uint8 _decimals\\n ) {\\n if (_requiredSignatures == 0) revert InvalidRequiredSignatures();\\n\\n REGISTRY = _contractRegistry;\\n REQUIRED_SIGNATURES = _requiredSignatures;\\n STAKING_BANK = IStakingBankStatic(_contractRegistry.requireAndGetAddress(\\\"StakingBank\\\"));\\n DECIMALS = _decimals;\\n DEPLOYED_AT = block.timestamp;\\n }\\n\\n /// @dev destroys old contract\\n /// there is sanity check that prevents abuse of destroy method\\n /// @param _name string feed key to verify, that contract was initialised\\n function destroy(string calldata _name) external {\\n if (REGISTRY.getAddressByString(NAME) == address(this)) revert ContractInUse();\\n\\n if (_prices[keccak256(abi.encodePacked(_name))].timestamp == 0 && DEPLOYED_AT + 3 days > block.timestamp) {\\n revert ContractNotInitialised();\\n }\\n\\n selfdestruct(payable(msg.sender));\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function update(\\n bytes32[] calldata _priceKeys,\\n PriceData[] calldata _priceDatas,\\n Signature[] calldata _signatures\\n ) external {\\n if (_priceKeys.length != _priceDatas.length) revert ArraysDataDoNotMatch();\\n\\n bytes32 priceDataHash = keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\\n verifySignatures(priceDataHash, _signatures);\\n\\n uint256 i;\\n\\n while (i < _priceDatas.length) {\\n bytes32 priceKey = _priceKeys[i];\\n\\n // we do not allow for older prices\\n // at the same time it prevents from reusing signatures\\n if (_prices[priceKey].timestamp >= _priceDatas[i].timestamp) revert OldData();\\n\\n _prices[priceKey] = _priceDatas[i];\\n\\n // atm there is no need for events, so in order to save gas, we do not emit any\\n unchecked { i++; }\\n }\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\\n data = new PriceData[](_keys.length);\\n\\n for (uint256 i; i < _keys.length;) {\\n data[i] = _prices[_keys[i]];\\n if (data[i].timestamp == 0) revert FeedNotExist();\\n\\n unchecked { i++; }\\n }\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\\n data = new PriceData[](_keys.length);\\n\\n for (uint256 i; i < _keys.length;) {\\n data[i] = _prices[_keys[i]];\\n unchecked { i++; }\\n }\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function prices(bytes32 _key) external view returns (PriceData memory data) {\\n data = _prices[_key];\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getPriceData(bytes32 _key) external view returns (PriceData memory data) {\\n data = _prices[_key];\\n if (data.timestamp == 0) revert FeedNotExist();\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getPrice(bytes32 _key) external view returns (uint128 price) {\\n PriceData memory data = _prices[_key];\\n if (data.timestamp == 0) revert FeedNotExist();\\n\\n return data.price;\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp) {\\n PriceData memory data = _prices[_key];\\n if (data.timestamp == 0) revert FeedNotExist();\\n\\n return (data.price, data.timestamp);\\n }\\n\\n function getPriceTimestampHeartbeat(bytes32 _key)\\n external\\n view\\n returns (uint128 price, uint32 timestamp, uint24 heartbeat)\\n {\\n PriceData memory data = _prices[_key];\\n if (data.timestamp == 0) revert FeedNotExist();\\n\\n return (data.price, data.timestamp, data.heartbeat);\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data) {\\n bytes32 key = keccak256(abi.encodePacked(_name));\\n data = _prices[key];\\n }\\n\\n /// @dev helper method for QA purposes\\n /// @return hash of data that are signed by validators (keys and priced data)\\n function hashData(bytes32[] calldata _priceKeys, PriceData[] calldata _priceDatas)\\n external\\n view\\n returns (bytes32)\\n {\\n return keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\\n }\\n\\n /// @param _hash hash of signed data\\n /// @param _signatures array of validators signatures\\n function verifySignatures(bytes32 _hash, Signature[] calldata _signatures) public view {\\n address prevSigner = address(0x0);\\n\\n if (_signatures.length < REQUIRED_SIGNATURES) revert NotEnoughSignatures();\\n\\n address[] memory validators = new address[](REQUIRED_SIGNATURES);\\n\\n // to save gas we check only required number of signatures\\n // case, where you can have part of signatures invalid but still enough valid in total is not supported\\n for (uint256 i; i < REQUIRED_SIGNATURES;) {\\n (uint8 v, bytes32 r, bytes32 s) = (_signatures[i].v, _signatures[i].r, _signatures[i].s);\\n\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n revert ECDSAInvalidSignatureS();\\n }\\n\\n if (uint8(v) != 27 && uint8(v) != 28) revert ECDSAInvalidSignatureV();\\n\\n address signer = recoverSigner(_hash, v, r, s);\\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\\n\\n // because we check only required number of signatures, any invalid one will cause revert\\n prevSigner = signer;\\n validators[i] = signer;\\n\\n unchecked { i++; }\\n }\\n\\n // bulk verification can optimise gas when we have 5 or more validators\\n if (!STAKING_BANK.verifyValidators(validators)) revert InvalidSigner();\\n }\\n\\n function getChainId() public view returns (uint256 id) {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n id := chainid()\\n }\\n }\\n\\n /// @param _hash hashed of data\\n /// @param _v part of signature\\n /// @param _r part of signature\\n /// @param _s part of signature\\n /// @return signer address\\n function recoverSigner(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _hash));\\n return ecrecover(hash, _v, _r, _s);\\n }\\n\\n /// @dev to follow Registrable interface\\n function getName() public pure returns (bytes32) {\\n return \\\"UmbrellaFeeds\\\";\\n }\\n}\\n\",\"keccak256\":\"0xf5dcfbbdfe5a5ed6e7579246363b10cdc0aa30580fec74025e0704c2b042d369\",\"license\":\"MIT\"}},\"version\":1}", "bytecode": "0x6101206040523480156200001257600080fd5b50604051620030a4380380620030a4833981810160405281019062000038919062000286565b60008261ffff160362000077576040517f458bb42100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff16815250508161ffff1660e08161ffff16815250508273ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b8152600401620000f49062000308565b602060405180830381865afa15801562000112573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000138919062000354565b73ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff16815250508060ff166101008160ff1681525050426080818152505050505062000386565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620001bd8262000190565b9050919050565b6000620001d182620001b0565b9050919050565b620001e381620001c4565b8114620001ef57600080fd5b50565b6000815190506200020381620001d8565b92915050565b600061ffff82169050919050565b620002228162000209565b81146200022e57600080fd5b50565b600081519050620002428162000217565b92915050565b600060ff82169050919050565b620002608162000248565b81146200026c57600080fd5b50565b600081519050620002808162000255565b92915050565b600080600060608486031215620002a257620002a16200018b565b5b6000620002b286828701620001f2565b9350506020620002c58682870162000231565b9250506040620002d8868287016200026f565b9150509250925092565b7f5374616b696e6742616e6b000000000000000000000000000000000000000000815250565b60006020820190506200031e60008301620002e2565b919050565b6200032e81620001b0565b81146200033a57600080fd5b50565b6000815190506200034e8162000323565b92915050565b6000602082840312156200036d576200036c6200018b565b5b60006200037d848285016200033d565b91505092915050565b60805160a05160c05160e05161010051612caf620003f560003960006108b10152600081816104e501528181610548015281816105ba01526116980152600081816107da01526116f501526000818161045e015261107e0152600081816111fd015261127a0152612caf6000f3fe608060405234801561001057600080fd5b50600436106101125760003560e01c806306433b1b1461011757806317d7de7c1461013557806324c89a491461015357806326559877146101715780632e0f26251461018d5780632e550693146101ab57806331d98b3f146101db5780633408e4701461020b578063385e05da1461022957806343fa6211146102595780635b38adc71461028957806360846bc6146102b95780636b9c3c7c146102e95780636ebb8cd2146103055780638a1194d31461032357806395f1cf301461035457806396594f66146103705780639ac18b19146103a2578063a3f4df7e146103c0578063c65a53ad146103de578063ccc6fd69146103fc578063d45167d01461042c575b600080fd5b61011f61045c565b60405161012c91906118df565b60405180910390f35b61013d610480565b60405161014a9190611913565b60405180910390f35b61015b6104a8565b60405161016891906119c7565b60405180910390f35b61018b60048036038101906101869190611a84565b6104e1565b005b6101956108af565b6040516101a29190611b00565b60405180910390f35b6101c560048036038101906101c09190611b71565b6108d3565b6040516101d29190611d39565b60405180910390f35b6101f560048036038101906101f09190611d5b565b610a54565b6040516102029190611d97565b60405180910390f35b610213610b77565b6040516102209190611dcb565b60405180910390f35b610243600480360381019061023e9190611b71565b610b7f565b6040516102509190611d39565b60405180910390f35b610273600480360381019061026e9190611d5b565b610d5e565b6040516102809190611e3b565b60405180910390f35b6102a3600480360381019061029e9190611eac565b610e7e565b6040516102b09190611e3b565b60405180910390f35b6102d360048036038101906102ce9190611d5b565b610f89565b6040516102e09190611e3b565b60405180910390f35b61030360048036038101906102fe9190611eac565b611065565b005b61030d611278565b60405161031a9190611dcb565b60405180910390f35b61033d60048036038101906103389190611d5b565b61129c565b60405161034b929190611f08565b60405180910390f35b61036e60048036038101906103699190611f87565b6113c8565b005b61038a60048036038101906103859190611d5b565b611560565b6040516103999392919061204a565b60405180910390f35b6103aa611696565b6040516103b7919061209e565b60405180910390f35b6103c86116ba565b6040516103d5919061210e565b60405180910390f35b6103e66116f3565b6040516103f39190612151565b60405180910390f35b6104166004803603810190610411919061216c565b611717565b6040516104239190611913565b60405180910390f35b61044660048036038101906104419190612219565b61175b565b60405161045391906122a1565b60405180910390f35b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f556d6272656c6c61466565647300000000000000000000000000000000000000905090565b6040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525081565b60007f000000000000000000000000000000000000000000000000000000000000000061ffff16838390501015610544576040517fe246dc6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000061ffff1667ffffffffffffffff811115610584576105836122bc565b5b6040519080825280602002602001820160405280156105b25781602001602082028036833780820191505090505b50905060005b7f000000000000000000000000000000000000000000000000000000000000000061ffff168110156107d75760008060008787858181106105fc576105fb6122eb565b5b9050606002016000016020810190610614919061231a565b888886818110610627576106266122eb565b5b90506060020160200135898987818110610644576106436122eb565b5b905060600201604001359250925092507f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08160001c11156106b1576040517f454ffaa700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601b8360ff16141580156106c95750601c8360ff1614155b15610700576040517f1afa741400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061070e8a85858561175b565b90508073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1610610775576040517f9079f69b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8096508086868151811061078c5761078b6122eb565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508480600101955050505050506105b8565b507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16631d4f9ce0826040518263ffffffff1660e01b81526004016108319190612405565b602060405180830381865afa15801561084e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610872919061245f565b6108a8576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60608282905067ffffffffffffffff8111156108f2576108f16122bc565b5b60405190808252806020026020018201604052801561092b57816020015b610918611818565b8152602001906001900390816109105790505b50905060005b83839050811015610a4d57600080858584818110610952576109516122eb565b5b9050602002013581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681525050828281518110610a3557610a346122eb565b5b60200260200101819052508080600101915050610931565b5092915050565b6000806000808481526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603610b6a576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060600151915050919050565b600046905090565b60608282905067ffffffffffffffff811115610b9e57610b9d6122bc565b5b604051908082528060200260200182016040528015610bd757816020015b610bc4611818565b815260200190600190039081610bbc5790505b50905060005b83839050811015610d5757600080858584818110610bfe57610bfd6122eb565b5b9050602002013581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681525050828281518110610ce157610ce06122eb565b5b60200260200101819052506000828281518110610d0157610d006122eb565b5b60200260200101516040015163ffffffff1603610d4a576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8080600101915050610bdd565b5092915050565b610d66611818565b6000808381526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603610e79576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b610e86611818565b60008383604051602001610e9b9291906124cb565b6040516020818303038152906040528051906020012090506000808281526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505091505092915050565b610f91611818565b6000808381526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815250509050919050565b3073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663e8f98f886040518060400160405280600d81526020017f556d6272656c6c614665656473000000000000000000000000000000000000008152506040518263ffffffff1660e01b815260040161110a919061210e565b602060405180830381865afa158015611127573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114b9190612510565b73ffffffffffffffffffffffffffffffffffffffff1603611198576040517f8c3e700900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600084846040516020016111b09291906124cb565b60405160208183030381529060405280519060200120815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff161480156112285750426203f4807f0000000000000000000000000000000000000000000000000000000000000000611226919061256c565b115b1561125f576040517fcf51b43b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff16ff5b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060008060008581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff16036113b4576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806060015181604001519250925050915091565b838390508686905014611407576040517f0cf7902300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611411610b77565b308888888860405160200161142b96959493929190612820565b60405160208183030381529060405280519060200120905061144e8184846104e1565b60005b85859050811015611556576000888883818110611471576114706122eb565b5b90506020020135905086868381811061148d5761148c6122eb565b5b90506080020160400160208101906114a59190612877565b63ffffffff1660008083815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff161061150e576040517f1251b2f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b868683818110611521576115206122eb565b5b90506080020160008083815260200190815260200160002081816115459190612ba1565b905050818060010192505050611451565b5050505050505050565b6000806000806000808681526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603611679576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806060015181604001518260200151935093509350509193909250565b7f000000000000000000000000000000000000000000000000000000000000000081565b6040518060400160405280600d81526020017f556d6272656c6c6146656564730000000000000000000000000000000000000081525081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000611721610b77565b308686868660405160200161173b96959493929190612820565b604051602081830303815290604052805190602001209050949350505050565b6000806040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250866040516020016117a6929190612c0c565b604051602081830303815290604052805190602001209050600181868686604051600081526020016040526040516117e19493929190612c34565b6020604051602081039080840390855afa158015611803573d6000803e3d6000fd5b50505060206040510351915050949350505050565b6040518060800160405280600060ff168152602001600062ffffff168152602001600063ffffffff16815260200160006fffffffffffffffffffffffffffffffff1681525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006118a56118a061189b84611860565b611880565b611860565b9050919050565b60006118b78261188a565b9050919050565b60006118c9826118ac565b9050919050565b6118d9816118be565b82525050565b60006020820190506118f460008301846118d0565b92915050565b6000819050919050565b61190d816118fa565b82525050565b60006020820190506119286000830184611904565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561196857808201518184015260208101905061194d565b83811115611977576000848401525b50505050565b6000601f19601f8301169050919050565b60006119998261192e565b6119a38185611939565b93506119b381856020860161194a565b6119bc8161197d565b840191505092915050565b600060208201905081810360008301526119e1818461198e565b905092915050565b600080fd5b600080fd5b6119fc816118fa565b8114611a0757600080fd5b50565b600081359050611a19816119f3565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112611a4457611a43611a1f565b5b8235905067ffffffffffffffff811115611a6157611a60611a24565b5b602083019150836060820283011115611a7d57611a7c611a29565b5b9250929050565b600080600060408486031215611a9d57611a9c6119e9565b5b6000611aab86828701611a0a565b935050602084013567ffffffffffffffff811115611acc57611acb6119ee565b5b611ad886828701611a2e565b92509250509250925092565b600060ff82169050919050565b611afa81611ae4565b82525050565b6000602082019050611b156000830184611af1565b92915050565b60008083601f840112611b3157611b30611a1f565b5b8235905067ffffffffffffffff811115611b4e57611b4d611a24565b5b602083019150836020820283011115611b6a57611b69611a29565b5b9250929050565b60008060208385031215611b8857611b876119e9565b5b600083013567ffffffffffffffff811115611ba657611ba56119ee565b5b611bb285828601611b1b565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b611bf381611ae4565b82525050565b600062ffffff82169050919050565b611c1181611bf9565b82525050565b600063ffffffff82169050919050565b611c3081611c17565b82525050565b60006fffffffffffffffffffffffffffffffff82169050919050565b611c5b81611c36565b82525050565b608082016000820151611c776000850182611bea565b506020820151611c8a6020850182611c08565b506040820151611c9d6040850182611c27565b506060820151611cb06060850182611c52565b50505050565b6000611cc28383611c61565b60808301905092915050565b6000602082019050919050565b6000611ce682611bbe565b611cf08185611bc9565b9350611cfb83611bda565b8060005b83811015611d2c578151611d138882611cb6565b9750611d1e83611cce565b925050600181019050611cff565b5085935050505092915050565b60006020820190508181036000830152611d538184611cdb565b905092915050565b600060208284031215611d7157611d706119e9565b5b6000611d7f84828501611a0a565b91505092915050565b611d9181611c36565b82525050565b6000602082019050611dac6000830184611d88565b92915050565b6000819050919050565b611dc581611db2565b82525050565b6000602082019050611de06000830184611dbc565b92915050565b608082016000820151611dfc6000850182611bea565b506020820151611e0f6020850182611c08565b506040820151611e226040850182611c27565b506060820151611e356060850182611c52565b50505050565b6000608082019050611e506000830184611de6565b92915050565b60008083601f840112611e6c57611e6b611a1f565b5b8235905067ffffffffffffffff811115611e8957611e88611a24565b5b602083019150836001820283011115611ea557611ea4611a29565b5b9250929050565b60008060208385031215611ec357611ec26119e9565b5b600083013567ffffffffffffffff811115611ee157611ee06119ee565b5b611eed85828601611e56565b92509250509250929050565b611f0281611c17565b82525050565b6000604082019050611f1d6000830185611d88565b611f2a6020830184611ef9565b9392505050565b60008083601f840112611f4757611f46611a1f565b5b8235905067ffffffffffffffff811115611f6457611f63611a24565b5b602083019150836080820283011115611f8057611f7f611a29565b5b9250929050565b60008060008060008060608789031215611fa457611fa36119e9565b5b600087013567ffffffffffffffff811115611fc257611fc16119ee565b5b611fce89828a01611b1b565b9650965050602087013567ffffffffffffffff811115611ff157611ff06119ee565b5b611ffd89828a01611f31565b9450945050604087013567ffffffffffffffff8111156120205761201f6119ee565b5b61202c89828a01611a2e565b92509250509295509295509295565b61204481611bf9565b82525050565b600060608201905061205f6000830186611d88565b61206c6020830185611ef9565b612079604083018461203b565b949350505050565b600061ffff82169050919050565b61209881612081565b82525050565b60006020820190506120b3600083018461208f565b92915050565b600081519050919050565b600082825260208201905092915050565b60006120e0826120b9565b6120ea81856120c4565b93506120fa81856020860161194a565b6121038161197d565b840191505092915050565b6000602082019050818103600083015261212881846120d5565b905092915050565b600061213b826118ac565b9050919050565b61214b81612130565b82525050565b60006020820190506121666000830184612142565b92915050565b60008060008060408587031215612186576121856119e9565b5b600085013567ffffffffffffffff8111156121a4576121a36119ee565b5b6121b087828801611b1b565b9450945050602085013567ffffffffffffffff8111156121d3576121d26119ee565b5b6121df87828801611f31565b925092505092959194509250565b6121f681611ae4565b811461220157600080fd5b50565b600081359050612213816121ed565b92915050565b60008060008060808587031215612233576122326119e9565b5b600061224187828801611a0a565b945050602061225287828801612204565b935050604061226387828801611a0a565b925050606061227487828801611a0a565b91505092959194509250565b600061228b82611860565b9050919050565b61229b81612280565b82525050565b60006020820190506122b66000830184612292565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156123305761232f6119e9565b5b600061233e84828501612204565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61237c81612280565b82525050565b600061238e8383612373565b60208301905092915050565b6000602082019050919050565b60006123b282612347565b6123bc8185612352565b93506123c783612363565b8060005b838110156123f85781516123df8882612382565b97506123ea8361239a565b9250506001810190506123cb565b5085935050505092915050565b6000602082019050818103600083015261241f81846123a7565b905092915050565b60008115159050919050565b61243c81612427565b811461244757600080fd5b50565b60008151905061245981612433565b92915050565b600060208284031215612475576124746119e9565b5b60006124838482850161244a565b91505092915050565b600081905092915050565b82818337600083830152505050565b60006124b2838561248c565b93506124bf838584612497565b82840190509392505050565b60006124d88284866124a6565b91508190509392505050565b6124ed81612280565b81146124f857600080fd5b50565b60008151905061250a816124e4565b92915050565b600060208284031215612526576125256119e9565b5b6000612534848285016124fb565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061257782611db2565b915061258283611db2565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156125b7576125b661253d565b5b828201905092915050565b600082825260208201905092915050565b600080fd5b60006125e483856125c2565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115612617576126166125d3565b5b602083029250612628838584612497565b82840190509392505050565b6000819050919050565b600061264d6020840184612204565b905092915050565b61265e81611bf9565b811461266957600080fd5b50565b60008135905061267b81612655565b92915050565b6000612690602084018461266c565b905092915050565b6126a181611c17565b81146126ac57600080fd5b50565b6000813590506126be81612698565b92915050565b60006126d360208401846126af565b905092915050565b6126e481611c36565b81146126ef57600080fd5b50565b600081359050612701816126db565b92915050565b600061271660208401846126f2565b905092915050565b6080820161272f600083018361263e565b61273c6000850182611bea565b5061274a6020830183612681565b6127576020850182611c08565b5061276560408301836126c4565b6127726040850182611c27565b506127806060830183612707565b61278d6060850182611c52565b50505050565b600061279f838361271e565b60808301905092915050565b600082905092915050565b6000608082019050919050565b60006127cf8385611bc9565b93506127da82612634565b8060005b85811015612813576127f082846127ab565b6127fa8882612793565b9750612805836127b6565b9250506001810190506127de565b5085925050509392505050565b60006080820190506128356000830189611dbc565b6128426020830188612292565b81810360408301526128558186886125d8565b9050818103606083015261286a8184866127c3565b9050979650505050505050565b60006020828403121561288d5761288c6119e9565b5b600061289b848285016126af565b91505092915050565b600081356128b1816121ed565b80915050919050565b60008160001b9050919050565b600060ff6128d4846128ba565b9350801983169250808416831791505092915050565b60006129056129006128fb84611ae4565b611880565b611ae4565b9050919050565b6000819050919050565b61291f826128ea565b61293261292b8261290c565b83546128c7565b8255505050565b6000813561294681612655565b80915050919050565b60008160081b9050919050565b600063ffffff0061296c8461294f565b9350801983169250808416831791505092915050565b600061299d61299861299384611bf9565b611880565b611bf9565b9050919050565b6000819050919050565b6129b782612982565b6129ca6129c3826129a4565b835461295c565b8255505050565b600081356129de81612698565b80915050919050565b60008160201b9050919050565b600067ffffffff00000000612a08846129e7565b9350801983169250808416831791505092915050565b6000612a39612a34612a2f84611c17565b611880565b611c17565b9050919050565b6000819050919050565b612a5382612a1e565b612a66612a5f82612a40565b83546129f4565b8255505050565b60008135612a7a816126db565b80915050919050565b60008160401b9050919050565b600077ffffffffffffffffffffffffffffffff0000000000000000612ab484612a83565b9350801983169250808416831791505092915050565b6000612ae5612ae0612adb84611c36565b611880565b611c36565b9050919050565b6000819050919050565b612aff82612aca565b612b12612b0b82612aec565b8354612a90565b8255505050565b600081016000830180612b2b816128a4565b9050612b378184612916565b505050600081016020830180612b4c81612939565b9050612b5881846129ae565b505050600081016040830180612b6d816129d1565b9050612b798184612a4a565b505050600081016060830180612b8e81612a6d565b9050612b9a8184612af6565b5050505050565b612bab8282612b19565b5050565b600081905092915050565b6000612bc58261192e565b612bcf8185612baf565b9350612bdf81856020860161194a565b80840191505092915050565b6000819050919050565b612c06612c01826118fa565b612beb565b82525050565b6000612c188285612bba565b9150612c248284612bf5565b6020820191508190509392505050565b6000608082019050612c496000830187611904565b612c566020830186611af1565b612c636040830185611904565b612c706060830184611904565b9594505050505056fea26469706673582212204e20478e2e3070a20aa83127753a448e1b78b26fd4b44673d2f1b4027a2cf6be64736f6c634300080d0033", "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101125760003560e01c806306433b1b1461011757806317d7de7c1461013557806324c89a491461015357806326559877146101715780632e0f26251461018d5780632e550693146101ab57806331d98b3f146101db5780633408e4701461020b578063385e05da1461022957806343fa6211146102595780635b38adc71461028957806360846bc6146102b95780636b9c3c7c146102e95780636ebb8cd2146103055780638a1194d31461032357806395f1cf301461035457806396594f66146103705780639ac18b19146103a2578063a3f4df7e146103c0578063c65a53ad146103de578063ccc6fd69146103fc578063d45167d01461042c575b600080fd5b61011f61045c565b60405161012c91906118df565b60405180910390f35b61013d610480565b60405161014a9190611913565b60405180910390f35b61015b6104a8565b60405161016891906119c7565b60405180910390f35b61018b60048036038101906101869190611a84565b6104e1565b005b6101956108af565b6040516101a29190611b00565b60405180910390f35b6101c560048036038101906101c09190611b71565b6108d3565b6040516101d29190611d39565b60405180910390f35b6101f560048036038101906101f09190611d5b565b610a54565b6040516102029190611d97565b60405180910390f35b610213610b77565b6040516102209190611dcb565b60405180910390f35b610243600480360381019061023e9190611b71565b610b7f565b6040516102509190611d39565b60405180910390f35b610273600480360381019061026e9190611d5b565b610d5e565b6040516102809190611e3b565b60405180910390f35b6102a3600480360381019061029e9190611eac565b610e7e565b6040516102b09190611e3b565b60405180910390f35b6102d360048036038101906102ce9190611d5b565b610f89565b6040516102e09190611e3b565b60405180910390f35b61030360048036038101906102fe9190611eac565b611065565b005b61030d611278565b60405161031a9190611dcb565b60405180910390f35b61033d60048036038101906103389190611d5b565b61129c565b60405161034b929190611f08565b60405180910390f35b61036e60048036038101906103699190611f87565b6113c8565b005b61038a60048036038101906103859190611d5b565b611560565b6040516103999392919061204a565b60405180910390f35b6103aa611696565b6040516103b7919061209e565b60405180910390f35b6103c86116ba565b6040516103d5919061210e565b60405180910390f35b6103e66116f3565b6040516103f39190612151565b60405180910390f35b6104166004803603810190610411919061216c565b611717565b6040516104239190611913565b60405180910390f35b61044660048036038101906104419190612219565b61175b565b60405161045391906122a1565b60405180910390f35b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f556d6272656c6c61466565647300000000000000000000000000000000000000905090565b6040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525081565b60007f000000000000000000000000000000000000000000000000000000000000000061ffff16838390501015610544576040517fe246dc6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000061ffff1667ffffffffffffffff811115610584576105836122bc565b5b6040519080825280602002602001820160405280156105b25781602001602082028036833780820191505090505b50905060005b7f000000000000000000000000000000000000000000000000000000000000000061ffff168110156107d75760008060008787858181106105fc576105fb6122eb565b5b9050606002016000016020810190610614919061231a565b888886818110610627576106266122eb565b5b90506060020160200135898987818110610644576106436122eb565b5b905060600201604001359250925092507f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08160001c11156106b1576040517f454ffaa700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601b8360ff16141580156106c95750601c8360ff1614155b15610700576040517f1afa741400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061070e8a85858561175b565b90508073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1610610775576040517f9079f69b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8096508086868151811061078c5761078b6122eb565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508480600101955050505050506105b8565b507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16631d4f9ce0826040518263ffffffff1660e01b81526004016108319190612405565b602060405180830381865afa15801561084e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610872919061245f565b6108a8576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60608282905067ffffffffffffffff8111156108f2576108f16122bc565b5b60405190808252806020026020018201604052801561092b57816020015b610918611818565b8152602001906001900390816109105790505b50905060005b83839050811015610a4d57600080858584818110610952576109516122eb565b5b9050602002013581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681525050828281518110610a3557610a346122eb565b5b60200260200101819052508080600101915050610931565b5092915050565b6000806000808481526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603610b6a576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060600151915050919050565b600046905090565b60608282905067ffffffffffffffff811115610b9e57610b9d6122bc565b5b604051908082528060200260200182016040528015610bd757816020015b610bc4611818565b815260200190600190039081610bbc5790505b50905060005b83839050811015610d5757600080858584818110610bfe57610bfd6122eb565b5b9050602002013581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681525050828281518110610ce157610ce06122eb565b5b60200260200101819052506000828281518110610d0157610d006122eb565b5b60200260200101516040015163ffffffff1603610d4a576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8080600101915050610bdd565b5092915050565b610d66611818565b6000808381526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603610e79576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b610e86611818565b60008383604051602001610e9b9291906124cb565b6040516020818303038152906040528051906020012090506000808281526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505091505092915050565b610f91611818565b6000808381526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815250509050919050565b3073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663e8f98f886040518060400160405280600d81526020017f556d6272656c6c614665656473000000000000000000000000000000000000008152506040518263ffffffff1660e01b815260040161110a919061210e565b602060405180830381865afa158015611127573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114b9190612510565b73ffffffffffffffffffffffffffffffffffffffff1603611198576040517f8c3e700900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600084846040516020016111b09291906124cb565b60405160208183030381529060405280519060200120815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff161480156112285750426203f4807f0000000000000000000000000000000000000000000000000000000000000000611226919061256c565b115b1561125f576040517fcf51b43b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff16ff5b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060008060008581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff16036113b4576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806060015181604001519250925050915091565b838390508686905014611407576040517f0cf7902300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611411610b77565b308888888860405160200161142b96959493929190612820565b60405160208183030381529060405280519060200120905061144e8184846104e1565b60005b85859050811015611556576000888883818110611471576114706122eb565b5b90506020020135905086868381811061148d5761148c6122eb565b5b90506080020160400160208101906114a59190612877565b63ffffffff1660008083815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff161061150e576040517f1251b2f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b868683818110611521576115206122eb565b5b90506080020160008083815260200190815260200160002081816115459190612ba1565b905050818060010192505050611451565b5050505050505050565b6000806000806000808681526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603611679576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806060015181604001518260200151935093509350509193909250565b7f000000000000000000000000000000000000000000000000000000000000000081565b6040518060400160405280600d81526020017f556d6272656c6c6146656564730000000000000000000000000000000000000081525081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000611721610b77565b308686868660405160200161173b96959493929190612820565b604051602081830303815290604052805190602001209050949350505050565b6000806040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250866040516020016117a6929190612c0c565b604051602081830303815290604052805190602001209050600181868686604051600081526020016040526040516117e19493929190612c34565b6020604051602081039080840390855afa158015611803573d6000803e3d6000fd5b50505060206040510351915050949350505050565b6040518060800160405280600060ff168152602001600062ffffff168152602001600063ffffffff16815260200160006fffffffffffffffffffffffffffffffff1681525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006118a56118a061189b84611860565b611880565b611860565b9050919050565b60006118b78261188a565b9050919050565b60006118c9826118ac565b9050919050565b6118d9816118be565b82525050565b60006020820190506118f460008301846118d0565b92915050565b6000819050919050565b61190d816118fa565b82525050565b60006020820190506119286000830184611904565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561196857808201518184015260208101905061194d565b83811115611977576000848401525b50505050565b6000601f19601f8301169050919050565b60006119998261192e565b6119a38185611939565b93506119b381856020860161194a565b6119bc8161197d565b840191505092915050565b600060208201905081810360008301526119e1818461198e565b905092915050565b600080fd5b600080fd5b6119fc816118fa565b8114611a0757600080fd5b50565b600081359050611a19816119f3565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112611a4457611a43611a1f565b5b8235905067ffffffffffffffff811115611a6157611a60611a24565b5b602083019150836060820283011115611a7d57611a7c611a29565b5b9250929050565b600080600060408486031215611a9d57611a9c6119e9565b5b6000611aab86828701611a0a565b935050602084013567ffffffffffffffff811115611acc57611acb6119ee565b5b611ad886828701611a2e565b92509250509250925092565b600060ff82169050919050565b611afa81611ae4565b82525050565b6000602082019050611b156000830184611af1565b92915050565b60008083601f840112611b3157611b30611a1f565b5b8235905067ffffffffffffffff811115611b4e57611b4d611a24565b5b602083019150836020820283011115611b6a57611b69611a29565b5b9250929050565b60008060208385031215611b8857611b876119e9565b5b600083013567ffffffffffffffff811115611ba657611ba56119ee565b5b611bb285828601611b1b565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b611bf381611ae4565b82525050565b600062ffffff82169050919050565b611c1181611bf9565b82525050565b600063ffffffff82169050919050565b611c3081611c17565b82525050565b60006fffffffffffffffffffffffffffffffff82169050919050565b611c5b81611c36565b82525050565b608082016000820151611c776000850182611bea565b506020820151611c8a6020850182611c08565b506040820151611c9d6040850182611c27565b506060820151611cb06060850182611c52565b50505050565b6000611cc28383611c61565b60808301905092915050565b6000602082019050919050565b6000611ce682611bbe565b611cf08185611bc9565b9350611cfb83611bda565b8060005b83811015611d2c578151611d138882611cb6565b9750611d1e83611cce565b925050600181019050611cff565b5085935050505092915050565b60006020820190508181036000830152611d538184611cdb565b905092915050565b600060208284031215611d7157611d706119e9565b5b6000611d7f84828501611a0a565b91505092915050565b611d9181611c36565b82525050565b6000602082019050611dac6000830184611d88565b92915050565b6000819050919050565b611dc581611db2565b82525050565b6000602082019050611de06000830184611dbc565b92915050565b608082016000820151611dfc6000850182611bea565b506020820151611e0f6020850182611c08565b506040820151611e226040850182611c27565b506060820151611e356060850182611c52565b50505050565b6000608082019050611e506000830184611de6565b92915050565b60008083601f840112611e6c57611e6b611a1f565b5b8235905067ffffffffffffffff811115611e8957611e88611a24565b5b602083019150836001820283011115611ea557611ea4611a29565b5b9250929050565b60008060208385031215611ec357611ec26119e9565b5b600083013567ffffffffffffffff811115611ee157611ee06119ee565b5b611eed85828601611e56565b92509250509250929050565b611f0281611c17565b82525050565b6000604082019050611f1d6000830185611d88565b611f2a6020830184611ef9565b9392505050565b60008083601f840112611f4757611f46611a1f565b5b8235905067ffffffffffffffff811115611f6457611f63611a24565b5b602083019150836080820283011115611f8057611f7f611a29565b5b9250929050565b60008060008060008060608789031215611fa457611fa36119e9565b5b600087013567ffffffffffffffff811115611fc257611fc16119ee565b5b611fce89828a01611b1b565b9650965050602087013567ffffffffffffffff811115611ff157611ff06119ee565b5b611ffd89828a01611f31565b9450945050604087013567ffffffffffffffff8111156120205761201f6119ee565b5b61202c89828a01611a2e565b92509250509295509295509295565b61204481611bf9565b82525050565b600060608201905061205f6000830186611d88565b61206c6020830185611ef9565b612079604083018461203b565b949350505050565b600061ffff82169050919050565b61209881612081565b82525050565b60006020820190506120b3600083018461208f565b92915050565b600081519050919050565b600082825260208201905092915050565b60006120e0826120b9565b6120ea81856120c4565b93506120fa81856020860161194a565b6121038161197d565b840191505092915050565b6000602082019050818103600083015261212881846120d5565b905092915050565b600061213b826118ac565b9050919050565b61214b81612130565b82525050565b60006020820190506121666000830184612142565b92915050565b60008060008060408587031215612186576121856119e9565b5b600085013567ffffffffffffffff8111156121a4576121a36119ee565b5b6121b087828801611b1b565b9450945050602085013567ffffffffffffffff8111156121d3576121d26119ee565b5b6121df87828801611f31565b925092505092959194509250565b6121f681611ae4565b811461220157600080fd5b50565b600081359050612213816121ed565b92915050565b60008060008060808587031215612233576122326119e9565b5b600061224187828801611a0a565b945050602061225287828801612204565b935050604061226387828801611a0a565b925050606061227487828801611a0a565b91505092959194509250565b600061228b82611860565b9050919050565b61229b81612280565b82525050565b60006020820190506122b66000830184612292565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156123305761232f6119e9565b5b600061233e84828501612204565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61237c81612280565b82525050565b600061238e8383612373565b60208301905092915050565b6000602082019050919050565b60006123b282612347565b6123bc8185612352565b93506123c783612363565b8060005b838110156123f85781516123df8882612382565b97506123ea8361239a565b9250506001810190506123cb565b5085935050505092915050565b6000602082019050818103600083015261241f81846123a7565b905092915050565b60008115159050919050565b61243c81612427565b811461244757600080fd5b50565b60008151905061245981612433565b92915050565b600060208284031215612475576124746119e9565b5b60006124838482850161244a565b91505092915050565b600081905092915050565b82818337600083830152505050565b60006124b2838561248c565b93506124bf838584612497565b82840190509392505050565b60006124d88284866124a6565b91508190509392505050565b6124ed81612280565b81146124f857600080fd5b50565b60008151905061250a816124e4565b92915050565b600060208284031215612526576125256119e9565b5b6000612534848285016124fb565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061257782611db2565b915061258283611db2565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156125b7576125b661253d565b5b828201905092915050565b600082825260208201905092915050565b600080fd5b60006125e483856125c2565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115612617576126166125d3565b5b602083029250612628838584612497565b82840190509392505050565b6000819050919050565b600061264d6020840184612204565b905092915050565b61265e81611bf9565b811461266957600080fd5b50565b60008135905061267b81612655565b92915050565b6000612690602084018461266c565b905092915050565b6126a181611c17565b81146126ac57600080fd5b50565b6000813590506126be81612698565b92915050565b60006126d360208401846126af565b905092915050565b6126e481611c36565b81146126ef57600080fd5b50565b600081359050612701816126db565b92915050565b600061271660208401846126f2565b905092915050565b6080820161272f600083018361263e565b61273c6000850182611bea565b5061274a6020830183612681565b6127576020850182611c08565b5061276560408301836126c4565b6127726040850182611c27565b506127806060830183612707565b61278d6060850182611c52565b50505050565b600061279f838361271e565b60808301905092915050565b600082905092915050565b6000608082019050919050565b60006127cf8385611bc9565b93506127da82612634565b8060005b85811015612813576127f082846127ab565b6127fa8882612793565b9750612805836127b6565b9250506001810190506127de565b5085925050509392505050565b60006080820190506128356000830189611dbc565b6128426020830188612292565b81810360408301526128558186886125d8565b9050818103606083015261286a8184866127c3565b9050979650505050505050565b60006020828403121561288d5761288c6119e9565b5b600061289b848285016126af565b91505092915050565b600081356128b1816121ed565b80915050919050565b60008160001b9050919050565b600060ff6128d4846128ba565b9350801983169250808416831791505092915050565b60006129056129006128fb84611ae4565b611880565b611ae4565b9050919050565b6000819050919050565b61291f826128ea565b61293261292b8261290c565b83546128c7565b8255505050565b6000813561294681612655565b80915050919050565b60008160081b9050919050565b600063ffffff0061296c8461294f565b9350801983169250808416831791505092915050565b600061299d61299861299384611bf9565b611880565b611bf9565b9050919050565b6000819050919050565b6129b782612982565b6129ca6129c3826129a4565b835461295c565b8255505050565b600081356129de81612698565b80915050919050565b60008160201b9050919050565b600067ffffffff00000000612a08846129e7565b9350801983169250808416831791505092915050565b6000612a39612a34612a2f84611c17565b611880565b611c17565b9050919050565b6000819050919050565b612a5382612a1e565b612a66612a5f82612a40565b83546129f4565b8255505050565b60008135612a7a816126db565b80915050919050565b60008160401b9050919050565b600077ffffffffffffffffffffffffffffffff0000000000000000612ab484612a83565b9350801983169250808416831791505092915050565b6000612ae5612ae0612adb84611c36565b611880565b611c36565b9050919050565b6000819050919050565b612aff82612aca565b612b12612b0b82612aec565b8354612a90565b8255505050565b600081016000830180612b2b816128a4565b9050612b378184612916565b505050600081016020830180612b4c81612939565b9050612b5881846129ae565b505050600081016040830180612b6d816129d1565b9050612b798184612a4a565b505050600081016060830180612b8e81612a6d565b9050612b9a8184612af6565b5050505050565b612bab8282612b19565b5050565b600081905092915050565b6000612bc58261192e565b612bcf8185612baf565b9350612bdf81856020860161194a565b80840191505092915050565b6000819050919050565b612c06612c01826118fa565b612beb565b82525050565b6000612c188285612bba565b9150612c248284612bf5565b6020820191508190509392505050565b6000608082019050612c496000830187611904565b612c566020830186611af1565b612c636040830185611904565b612c706060830184611904565b9594505050505056fea26469706673582212204e20478e2e3070a20aa83127753a448e1b78b26fd4b44673d2f1b4027a2cf6be64736f6c634300080d0033", diff --git a/deployments/bob_production/solcInputs/dc68422c0ad35a4fe46d461b096b9383.json b/deployments/bob_production/solcInputs/dc68422c0ad35a4fe46d461b096b9383.json new file mode 100644 index 00000000..43238985 --- /dev/null +++ b/deployments/bob_production/solcInputs/dc68422c0ad35a4fe46d461b096b9383.json @@ -0,0 +1,125 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n }\n _balances[to] += amount;\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n _balances[account] += amount;\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n }\n _totalSupply -= amount;\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Trees proofs.\n *\n * The proofs can be generated using the JavaScript library\n * https://github.com/miguelmota/merkletreejs[merkletreejs].\n * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.\n *\n * See `test/utils/cryptography/MerkleProof.test.js` for some examples.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(\n bytes32[] memory proof,\n bytes32 root,\n bytes32 leaf\n ) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n bytes32 proofElement = proof[i];\n if (computedHash <= proofElement) {\n // Hash(current computed hash + current element of the proof)\n computedHash = _efficientHash(computedHash, proofElement);\n } else {\n // Hash(current element of the proof + current computed hash)\n computedHash = _efficientHash(proofElement, computedHash);\n }\n }\n return computedHash;\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "@umb-network/toolbox/dist/contracts/lib/ValueDecoder.sol": { + "content": "//SPDX-License-Identifier: Unlicensed\npragma solidity >=0.6.8;\n\nlibrary ValueDecoder {\n function toUint(bytes memory _bytes) internal pure returns (uint256 value) {\n assembly {\n value := mload(add(_bytes, 32))\n }\n }\n\n function toUint(bytes32 _bytes) internal pure returns (uint256 value) {\n assembly {\n value := _bytes\n }\n }\n\n function toInt(uint224 u) internal pure returns (int256) {\n int224 i;\n uint224 max = type(uint224).max;\n\n if (u <= (max - 1) / 2) { // positive values\n assembly {\n i := add(u, 0)\n }\n\n return i;\n } else { // negative values\n assembly {\n i := sub(sub(u, max), 1)\n }\n }\n\n return i;\n }\n}\n\n" + }, + "contracts/BaseChain.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\";\nimport \"@umb-network/toolbox/dist/contracts/lib/ValueDecoder.sol\";\n\nimport \"./interfaces/IBaseChainV1.sol\";\nimport \"./interfaces/IStakingBank.sol\";\nimport \"./extensions/Registrable.sol\";\nimport \"./Registry.sol\";\n\nabstract contract BaseChain is Registrable, Ownable {\n using ValueDecoder for bytes;\n using ValueDecoder for uint224;\n using MerkleProof for bytes32[];\n\n /// @param root merkle root for consensus\n /// @param dataTimestamp consensus timestamp\n struct Block {\n bytes32 root;\n uint32 dataTimestamp;\n }\n\n /// @param value FCD value\n /// @param dataTimestamp FCD timestamp\n struct FirstClassData {\n uint224 value;\n uint32 dataTimestamp;\n }\n\n /// @param blocksCountOffset number of all blocks that were generated before switching to this contract\n /// @param sequence is a total number of blocks (consensus rounds) including previous contracts\n /// @param lastTimestamp is a timestamp of last submitted block\n /// @param padding number of seconds that need to pass before new submit will be possible\n /// @param deprecated flag that changes to TRUE on `unregister`, when TRUE submissions are not longer available\n struct ConsensusData {\n uint32 blocksCountOffset;\n uint32 sequence;\n uint32 lastTimestamp;\n uint32 padding;\n bool deprecated;\n }\n\n uint256 constant public VERSION = 2;\n\n bool internal immutable _ALLOW_FOR_MIXED_TYPE; // solhint-disable-line var-name-mixedcase\n\n bytes4 constant private _VERSION_SELECTOR = bytes4(keccak256(\"VERSION()\"));\n\n /// @dev minimal number of signatures required for accepting submission (PoA)\n uint16 internal immutable _REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\n\n ConsensusData internal _consensusData;\n\n bytes constant public ETH_PREFIX = \"\\x19Ethereum Signed Message:\\n32\";\n\n /// @dev block id (consensus ID) => root\n /// consensus ID is at the same time consensus timestamp\n mapping(uint256 => bytes32) public roots;\n\n /// @dev FCD key => FCD data\n mapping(bytes32 => FirstClassData) public fcds;\n\n event LogDeprecation(address indexed deprecator);\n event LogPadding(address indexed executor, uint32 timePadding);\n\n error ArraysDataDoNotMatch();\n error AlreadyDeprecated();\n error AlreadyRegistered();\n error BlockSubmittedToFastOrDataToOld();\n error ContractNotReady();\n error FCDOverflow();\n error InvalidContractType();\n error NoChangeToState();\n error OnlyOwnerOrRegistry();\n error UnregisterFirst();\n\n modifier onlyOwnerOrRegistry () {\n if (msg.sender != address(contractRegistry) && msg.sender != owner()) revert OnlyOwnerOrRegistry();\n _;\n }\n\n /// @param _contractRegistry Registry address\n /// @param _padding required \"space\" between blocks in seconds\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n constructor(\n IRegistry _contractRegistry,\n uint32 _padding,\n uint16 _requiredSignatures,\n bool _allowForMixedType\n ) Registrable(_contractRegistry) {\n _ALLOW_FOR_MIXED_TYPE = _allowForMixedType;\n _REQUIRED_SIGNATURES = _requiredSignatures;\n\n _setPadding(_padding);\n\n BaseChain oldChain = BaseChain(_contractRegistry.getAddress(\"Chain\"));\n\n if (address(oldChain) == address(0)) {\n // if this is first contract in sidechain, then we need to initialise lastTimestamp so submission\n // can be possible\n _consensusData.lastTimestamp = uint32(block.timestamp) - _padding - 1;\n }\n }\n\n /// @dev setter for `padding`\n function setPadding(uint16 _padding) external {\n _setPadding(_padding);\n }\n\n /// @notice if this method needs to be called manually (not from Registry)\n /// it is important to do it as part of tx batch\n /// eg using multisig, we should prepare set of transactions and confirm them all at once\n /// @inheritdoc Registrable\n function register() external override onlyOwnerOrRegistry {\n address oldChain = contractRegistry.getAddress(\"Chain\");\n\n // registration must be done before address in registry is replaced\n if (oldChain == address(this)) revert AlreadyRegistered();\n\n if (oldChain == address(0x0)) {\n return;\n }\n\n _cloneLastDataFromPrevChain(oldChain);\n }\n\n /// @inheritdoc Registrable\n function unregister() external override onlyOwnerOrRegistry {\n // in case we deprecated contract manually, we simply return\n if (_consensusData.deprecated) return;\n\n address newChain = contractRegistry.getAddress(\"Chain\");\n // unregistering must be done after address in registry is replaced\n if (newChain == address(this)) revert UnregisterFirst();\n\n // TODO:\n // I think we need to remove restriction for type (at least once)\n // when we will switch to multichain architecture\n\n if (!_ALLOW_FOR_MIXED_TYPE) {\n // can not be replaced with chain of different type\n if (BaseChain(newChain).isForeign() != this.isForeign()) revert InvalidContractType();\n }\n\n _consensusData.deprecated = true;\n emit LogDeprecation(msg.sender);\n }\n\n /// @notice it allows to deprecate contract manually\n /// Only new Registry calls `unregister()` where we set deprecated to true\n /// In old Registries we don't have this feature, so in order to safely redeploy new Chain\n /// we will have to first deprecate current contract manually, then register new contract\n function deprecate() external onlyOwnerOrRegistry {\n if (_consensusData.deprecated) revert AlreadyDeprecated();\n\n _consensusData.deprecated = true;\n emit LogDeprecation(msg.sender);\n }\n\n /// @dev getter for `_consensusData`\n function getConsensusData() external view returns (ConsensusData memory) {\n return _consensusData;\n }\n\n /// @dev number of blocks (consensus rounds) saved in this contract\n function blocksCount() external view returns (uint256) {\n return _consensusData.sequence - _consensusData.blocksCountOffset;\n }\n\n function blocksCountOffset() external view returns (uint32) {\n return _consensusData.blocksCountOffset;\n }\n\n function lastBlockId() external view returns (uint256) {\n return _consensusData.lastTimestamp;\n }\n\n /// @return TRUE if contract is ForeignChain, FALSE otherwise\n function isForeign() external pure virtual returns (bool);\n\n /// @inheritdoc Registrable\n function getName() external pure override returns (bytes32) {\n return \"Chain\";\n }\n\n /// @param _affidavit root and FCDs hashed together\n /// @param _v part of signature\n /// @param _r part of signature\n /// @param _s part of signature\n /// @return signer address\n function recoverSigner(bytes32 _affidavit, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _affidavit));\n return ecrecover(hash, _v, _r, _s);\n }\n\n /// @param _blockId ID of submitted block\n /// @return block data (root + timestamp)\n function blocks(uint256 _blockId) external view returns (Block memory) {\n return Block(roots[_blockId], uint32(_blockId));\n }\n\n /// @return current block ID\n /// please note, that current ID is not the same as last ID, current means that once padding pass,\n /// ID will switch to next one and it will be pointing to empty submit until submit for that ID is done\n function getBlockId() external view returns (uint32) {\n if (_consensusData.lastTimestamp == 0) return 0;\n\n return getBlockIdAtTimestamp(block.timestamp);\n }\n\n function requiredSignatures() external view returns (uint16) {\n return _REQUIRED_SIGNATURES;\n }\n\n /// @dev calculates block ID for provided timestamp\n /// this function does not works for past timestamps\n /// @param _timestamp current or future timestamp\n /// @return block ID for provided timestamp\n function getBlockIdAtTimestamp(uint256 _timestamp) virtual public view returns (uint32) {\n ConsensusData memory data = _consensusData;\n\n unchecked {\n // we can't overflow because we adding two `uint32`\n if (data.lastTimestamp + data.padding < _timestamp) {\n return uint32(_timestamp);\n }\n }\n\n return data.lastTimestamp;\n }\n\n /// @return last submitted block ID, please note, that on deployment, when there is no submission for this contract\n /// block for last ID will be available in previous contract\n function getLatestBlockId() virtual public view returns (uint32) {\n return _consensusData.lastTimestamp;\n }\n\n /// @dev verifies if the leaf is valid leaf for merkle tree\n /// @param _proof merkle proof for merkle tree\n /// @param _root merkle root\n /// @param _leaf leaf hash\n /// @return TRUE if `_leaf` is valid, FALSE otherwise\n function verifyProof(bytes32[] memory _proof, bytes32 _root, bytes32 _leaf) public pure returns (bool) {\n if (_root == bytes32(0)) {\n return false;\n }\n\n return _proof.verify(_root, _leaf);\n }\n\n /// @dev creates leaf hash, that has is used in merkle tree\n /// @param _key key under which we store the value\n /// @param _value value itself as bytes\n /// @return leaf hash\n function hashLeaf(bytes memory _key, bytes memory _value) public pure returns (bytes32) {\n return keccak256(abi.encodePacked(_key, _value));\n }\n\n /// @dev verifies, if provided key-value pair was part of consensus\n /// @param _blockId consensus ID for which we doing a check\n /// @param _proof merkle proof for pair\n /// @param _key pair key\n /// @param _value pair value\n /// @return TRUE if key-value par was part of consensus, FALSE otherwise\n function verifyProofForBlock(\n uint256 _blockId,\n bytes32[] memory _proof,\n bytes memory _key,\n bytes memory _value\n )\n public\n view\n returns (bool)\n {\n return _proof.verify(roots[_blockId], keccak256(abi.encodePacked(_key, _value)));\n }\n\n /// @dev this is helper method, that extracts one merkle proof from many hashed provided as bytes\n /// @param _data many hashes as bytes\n /// @param _offset this is starting point for extraction\n /// @param _items how many hashes to extract\n /// @return merkle proof (array of bytes32 hashes)\n function bytesToBytes32Array(\n bytes memory _data,\n uint256 _offset,\n uint256 _items\n )\n public\n pure\n returns (bytes32[] memory)\n {\n bytes32[] memory dataList = new bytes32[](_items);\n\n // we can unchecked because we working only with `i` and `_offset`\n // in case of wrong `_offset` it will throw\n unchecked {\n for (uint256 i = 0; i < _items; i++) {\n bytes32 temp;\n uint256 idx = (i + 1 + _offset) * 32;\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n temp := mload(add(_data, idx))\n }\n\n dataList[i] = temp;\n }\n }\n\n return (dataList);\n }\n\n /// @dev batch method for data verification\n /// @param _blockIds consensus IDs for which we doing a checks\n /// @param _proofs merkle proofs for all pair, sequence of hashes provided as bytes\n /// @param _proofItemsCounter array of counters, each counter tells how many hashes proof for each leaf has\n /// @param _leaves array of merkle leaves\n /// @return results array of verification results, TRUE if leaf is part of consensus, FALSE otherwise\n function verifyProofs(\n uint32[] memory _blockIds,\n bytes memory _proofs,\n uint256[] memory _proofItemsCounter,\n bytes32[] memory _leaves\n )\n public\n view\n returns (bool[] memory results)\n {\n results = new bool[](_leaves.length);\n uint256 offset = 0;\n\n for (uint256 i = 0; i < _leaves.length;) {\n results[i] = bytesToBytes32Array(_proofs, offset, _proofItemsCounter[i]).verify(\n roots[_blockIds[i]], _leaves[i]\n );\n\n unchecked {\n // we can uncheck because it will not overflow in a lifetime, and if someone provide invalid counter\n // we verification will not be valid (or we throw because of invalid memory access)\n offset += _proofItemsCounter[i];\n // we can uncheck because `i` will not overflow in a lifetime\n i++;\n }\n }\n }\n\n /// @param _blockId consensus ID\n /// @return root for provided consensus ID\n function getBlockRoot(uint32 _blockId) external view returns (bytes32) {\n return roots[_blockId];\n }\n\n /// @param _blockId consensus ID\n /// @return timestamp for provided consensus ID\n function getBlockTimestamp(uint32 _blockId) external view returns (uint32) {\n return roots[_blockId] == bytes32(0) ? 0 : _blockId;\n }\n\n /// @dev batch getter for FCDs\n /// @param _keys FCDs keys to fetch\n /// @return values array of FCDs values\n /// @return timestamps array of FCDs timestamps\n function getCurrentValues(bytes32[] calldata _keys)\n external\n view\n returns (uint256[] memory values, uint32[] memory timestamps)\n {\n timestamps = new uint32[](_keys.length);\n values = new uint256[](_keys.length);\n\n for (uint i=0; i<_keys.length;) {\n FirstClassData storage numericFCD = fcds[_keys[i]];\n values[i] = uint256(numericFCD.value);\n timestamps[i] = numericFCD.dataTimestamp;\n\n unchecked {\n // we can uncheck because `i` will not overflow in a lifetime\n i++;\n }\n }\n }\n\n /// @dev getter for single FCD value\n /// @param _key FCD key\n /// @return value FCD value\n /// @return timestamp FCD timestamp\n function getCurrentValue(bytes32 _key) external view returns (uint256 value, uint256 timestamp) {\n FirstClassData storage numericFCD = fcds[_key];\n return (uint256(numericFCD.value), numericFCD.dataTimestamp);\n }\n\n /// @dev getter for single FCD value in case its type is `int`\n /// @param _key FCD key\n /// @return value FCD value\n /// @return timestamp FCD timestamp\n function getCurrentIntValue(bytes32 _key) external view returns (int256 value, uint256 timestamp) {\n FirstClassData storage numericFCD = fcds[_key];\n return (numericFCD.value.toInt(), numericFCD.dataTimestamp);\n }\n\n function _setPadding(uint32 _padding) internal onlyOwner {\n if (_consensusData.padding == _padding) revert NoChangeToState();\n\n _consensusData.padding = _padding;\n emit LogPadding(msg.sender, _padding);\n }\n\n /// @dev we cloning last block time, because we will need reference point for next submissions\n function _cloneLastDataFromPrevChain(address _prevChain) internal {\n (bool success, bytes memory v) = _prevChain.staticcall(abi.encode(_VERSION_SELECTOR));\n uint256 prevVersion = success ? abi.decode(v, (uint256)) : 1;\n\n if (prevVersion == 1) {\n uint32 latestId = IBaseChainV1(address(_prevChain)).getLatestBlockId();\n _consensusData.lastTimestamp = IBaseChainV1(address(_prevChain)).getBlockTimestamp(latestId);\n\n // +1 because getLatestBlockId subtracts 1\n // +1 because it might be situation when tx is already in progress in old contract\n // and old contract do not have deprecated flag\n _consensusData.sequence = latestId + 2;\n _consensusData.blocksCountOffset = latestId + 2;\n } else { // VERSION 2\n // with new Registry, we have register/unregister methods\n // Chain will be deprecated, so there is no need to do \"+1\" as in old version\n // TODO what with current Registries??\n // we need a way to make it deprecated!\n ConsensusData memory data = BaseChain(_prevChain).getConsensusData();\n\n _consensusData.sequence = data.sequence;\n _consensusData.blocksCountOffset = data.sequence;\n _consensusData.lastTimestamp = data.lastTimestamp;\n }\n }\n}\n" + }, + "contracts/Chain.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./BaseChain.sol\";\n\ncontract Chain is BaseChain {\n IStakingBank public immutable stakingBank;\n\n event LogMint(address indexed minter, uint256 blockId, uint256 staked, uint256 power);\n event LogVoter(uint256 indexed blockId, address indexed voter, uint256 vote);\n\n error NotEnoughSignatures();\n error SignaturesOutOfOrder();\n\n /// @param _contractRegistry Registry address\n /// @param _padding required \"space\" between blocks in seconds\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n /// @param _allowForMixedType we have two \"types\" of Chain: HomeChain and ForeignChain, when we redeploying\n /// we don't want to mix up them, so we checking, if new Chain has the same type as current one.\n /// However, when we will be switching from one homechain to another one, we have to allow for this mixing up.\n /// This flag will tell contract, if this is the case.\n constructor(\n IRegistry _contractRegistry,\n uint32 _padding,\n uint16 _requiredSignatures,\n bool _allowForMixedType\n ) BaseChain(_contractRegistry, _padding, _requiredSignatures, _allowForMixedType) {\n stakingBank = IStakingBank(_contractRegistry.requireAndGetAddress(\"StakingBank\"));\n }\n\n /// @dev method for submitting consensus data\n /// @param _dataTimestamp consensus timestamp, this is time for all data in merkle tree including FCDs\n /// @param _root merkle root\n /// @param _keys FCDs keys\n /// @param _values FCDs values\n /// @param _v array of `v` part of validators signatures\n /// @param _r array of `r` part of validators signatures\n /// @param _s array of `s` part of validators signatures\n // solhint-disable-next-line function-max-lines, code-complexity\n function submit(\n uint32 _dataTimestamp,\n bytes32 _root,\n bytes32[] memory _keys,\n uint256[] memory _values,\n uint8[] memory _v,\n bytes32[] memory _r,\n bytes32[] memory _s\n ) external {\n // below two checks are only for pretty errors, so we can safe gas and allow for raw revert\n // if (_keys.length != _values.length) revert ArraysDataDoNotMatch();\n // if (_v.length != _r.length || _r.length != _s.length) revert ArraysDataDoNotMatch();\n\n _verifySubmitTimestampAndIncSequence(_dataTimestamp);\n\n // we can't expect minter will have exactly the same timestamp\n // but for sure we can demand not to be off by a lot, that's why +3sec\n // temporary remove this condition, because recently on ropsten we see cases when minter/node\n // can be even 100sec behind\n // require(_dataTimestamp <= block.timestamp + 3,\n // string(abi.encodePacked(\"oh, so you can predict the future:\", _dataTimestamp - block.timestamp + 48)));\n\n bytes memory testimony = abi.encodePacked(_dataTimestamp, _root);\n\n for (uint256 i = 0; i < _keys.length;) {\n if (uint224(_values[i]) != _values[i]) revert FCDOverflow();\n\n fcds[_keys[i]] = FirstClassData(uint224(_values[i]), _dataTimestamp);\n testimony = abi.encodePacked(testimony, _keys[i], _values[i]);\n\n unchecked {\n // we can't pass enough data to overflow\n i++;\n }\n }\n\n uint256 signatures = 0;\n uint256 power = 0;\n //uint256 staked = stakingBank.totalSupply();\n bytes32 affidavit = keccak256(testimony);\n\n address prevSigner = address(0x0);\n\n for (uint256 i; i < _v.length;) {\n address signer = recoverSigner(affidavit, _v[i], _r[i], _s[i]);\n uint256 balance = stakingBank.balanceOf(signer);\n\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\n\n prevSigner = signer;\n\n if (balance == 0) {\n unchecked { i++; }\n continue;\n }\n\n signatures++;\n emit LogVoter(uint256(_dataTimestamp), signer, balance);\n\n unchecked {\n // we can't overflow because that means token overflowed\n // and even if we do, we will get lower power\n power += balance;\n i++;\n }\n }\n\n if (signatures < _REQUIRED_SIGNATURES) revert NotEnoughSignatures();\n\n emit LogMint(msg.sender, _dataTimestamp, stakingBank.totalSupply(), power);\n\n // TODO remember to protect against flash loans when DPoS will be in place\n // we turn on power once we have DPoS in action, we have PoA now\n // require(power * 100 / staked >= 66, \"not enough power was gathered\");\n\n roots[_dataTimestamp] = _root;\n _consensusData.lastTimestamp = _dataTimestamp;\n }\n\n /// @inheritdoc BaseChain\n function isForeign() external pure virtual override returns (bool) {\n return false;\n }\n\n /// @dev helper method that returns all important data about current state of contract\n /// @return blockNumber `block.number`\n /// @return timePadding `this.padding`\n /// @return lastDataTimestamp timestamp for last submitted consensus\n /// @return lastId ID of last submitted consensus\n /// @return nextLeader leader for `block.timestamp + 1`\n /// @return nextBlockId block ID for `block.timestamp + padding`\n /// @return validators array of all validators addresses\n /// @return powers array of all validators powers\n /// @return locations array of all validators locations\n /// @return staked total UMB staked by validators\n /// @return minSignatures `this.requiredSignatures`\n function getStatus() external view virtual returns(\n uint256 blockNumber,\n uint32 timePadding,\n uint32 lastDataTimestamp,\n uint32 lastId,\n address nextLeader,\n uint32 nextBlockId,\n address[] memory validators,\n uint256[] memory powers,\n string[] memory locations,\n uint256 staked,\n uint16 minSignatures\n ) {\n ConsensusData memory data = _consensusData;\n\n blockNumber = block.number;\n timePadding = data.padding;\n lastId = data.lastTimestamp;\n lastDataTimestamp = lastId;\n minSignatures = _REQUIRED_SIGNATURES;\n\n staked = stakingBank.totalSupply();\n uint256 numberOfValidators = stakingBank.getNumberOfValidators();\n powers = new uint256[](numberOfValidators);\n validators = new address[](numberOfValidators);\n locations = new string[](numberOfValidators);\n\n for (uint256 i = 0; i < numberOfValidators;) {\n validators[i] = stakingBank.addresses(i);\n (, locations[i]) = stakingBank.validators(validators[i]);\n powers[i] = stakingBank.balanceOf(validators[i]);\n\n unchecked {\n // we will run out of gas before overflow happen\n i++;\n }\n }\n\n unchecked {\n // we will not overflow with timestamp in a lifetime\n nextBlockId = lastId + data.padding + 1;\n\n nextLeader = numberOfValidators > 0\n // we will not overflow with timestamp in a lifetime\n ? validators[getLeaderIndex(numberOfValidators, block.timestamp + 1)]\n : address(0);\n }\n }\n\n /// @return address of leader for next second\n function getNextLeaderAddress() external view returns (address) {\n return getLeaderAddressAtTime(block.timestamp + 1);\n }\n\n /// @return address of current leader\n function getLeaderAddress() external view returns (address) {\n return getLeaderAddressAtTime(block.timestamp);\n }\n\n /// @param _numberOfValidators total number of validators\n /// @param _timestamp timestamp for which you want to calculate index\n /// @return leader index, use it for StakingBank.addresses[index] to fetch leader address\n function getLeaderIndex(uint256 _numberOfValidators, uint256 _timestamp) public view virtual returns (uint256) {\n ConsensusData memory data = _consensusData;\n\n unchecked {\n // we will not overflow on `timestamp` and `padding` in a life time\n // timePadding + 1 => because padding is a space between blocks,\n // so next round starts on first block after padding\n // TODO will it work for off-chain??\n uint256 validatorIndex = data.sequence + (_timestamp - data.lastTimestamp) / (data.padding + 1);\n\n return validatorIndex % _numberOfValidators;\n }\n }\n\n // @todo - properly handled non-enabled validators, newly added validators, and validators with low stake\n /// @param _timestamp timestamp for which you want to calculate leader address\n /// @return leader address for provider timestamp\n function getLeaderAddressAtTime(uint256 _timestamp) public view virtual returns (address) {\n uint256 numberOfValidators = stakingBank.getNumberOfValidators();\n\n if (numberOfValidators == 0) {\n return address(0x0);\n }\n\n uint256 validatorIndex = getLeaderIndex(numberOfValidators, _timestamp);\n\n return stakingBank.addresses(validatorIndex);\n }\n\n /// @dev we had stack too deep in `submit` so this method was created as a solution\n // we increasing `_consensusData.sequence` here so we don't have to read sequence again in other place\n function _verifySubmitTimestampAndIncSequence(uint256 _dataTimestamp) internal {\n ConsensusData memory data = _consensusData;\n\n // `data.lastTimestamp` must be setup either on deployment\n // or via cloning from previous contract\n if (data.lastTimestamp == 0) revert ContractNotReady();\n\n unchecked {\n // we will not overflow with timestamp and padding in a life time\n if (data.lastTimestamp + data.padding >= _dataTimestamp) revert BlockSubmittedToFastOrDataToOld();\n }\n\n unchecked {\n // we will not overflow in a life time\n _consensusData.sequence = uint32(data.sequence + 1);\n }\n }\n}\n" + }, + "contracts/extensions/Registrable.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\n/// @dev Any contract that we want to register in ContractRegistry, must inherit from Registrable\nabstract contract Registrable {\n IRegistry public immutable contractRegistry;\n\n modifier onlyFromContract(address _msgSender, bytes32 _contractName) {\n require(\n contractRegistry.getAddress(_contractName) == _msgSender,\n string(abi.encodePacked(\"caller is not \", _contractName))\n );\n _;\n }\n\n modifier withRegistrySetUp() {\n require(address(contractRegistry) != address(0x0), \"_registry is empty\");\n _;\n }\n\n constructor(IRegistry _contractRegistry) {\n require(address(_contractRegistry) != address(0x0), \"_registry is empty\");\n contractRegistry = _contractRegistry;\n }\n\n /// @dev this method will be called as a first method in registration process when old contract will be replaced\n /// when called, old contract address is still in registry\n function register() virtual external;\n\n /// @dev this method will be called as a last method in registration process when old contract will be replaced\n /// when called, new contract address is already in registry\n function unregister() virtual external;\n\n /// @return contract name as bytes32\n function getName() virtual external pure returns (bytes32);\n\n /// @dev helper method for fetching StakingBank address\n function stakingBankContract() public view returns (IStakingBank) {\n return IStakingBank(contractRegistry.requireAndGetAddress(\"StakingBank\"));\n }\n\n /// @dev helper method for fetching UMB address\n function tokenContract() public view withRegistrySetUp returns (ERC20) {\n return ERC20(contractRegistry.requireAndGetAddress(\"UMB\"));\n }\n}\n" + }, + "contracts/ForeignChain.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./Chain.sol\";\n\n/// @dev contract for foreign chains\ncontract ForeignChain is Chain {\n error NotSupported();\n\n /// @param _contractRegistry Registry address\n /// @param _padding required \"space\" between blocks in seconds\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n constructor(\n IRegistry _contractRegistry,\n uint32 _padding,\n uint16 _requiredSignatures,\n bool _allowForMixedType\n ) Chain(_contractRegistry, _padding, _requiredSignatures, _allowForMixedType) {\n // no additional configuration needed\n }\n\n /// @inheritdoc BaseChain\n function isForeign() external pure override returns (bool) {\n return true;\n }\n\n /// @inheritdoc Chain\n /// @notice this method is made to be compatible with MasterChain, but it does not return full data eg validators\n /// data will be missing.\n /// @return blockNumber `block.number`\n /// @return timePadding `this.padding`\n /// @return lastDataTimestamp timestamp for last submitted consensus\n /// @return lastId ID of last submitted consensus\n /// @return nextLeader will be always address(0)\n /// @return nextBlockId block ID for `block.timestamp + padding`\n /// @return validators array will be always empty\n /// @return powers array will be always empty\n /// @return locations array will be always empty\n /// @return staked total UMB staked by validators\n /// @return minSignatures `this.requiredSignatures`\n function getStatus() external view override returns(\n uint256 blockNumber,\n uint32 timePadding,\n uint32 lastDataTimestamp,\n uint32 lastId,\n address nextLeader,\n uint32 nextBlockId,\n address[] memory validators,\n uint256[] memory powers,\n string[] memory locations,\n uint256 staked,\n uint16 minSignatures\n ) {\n ConsensusData memory data = _consensusData;\n\n blockNumber = block.number;\n timePadding = data.padding;\n lastId = data.lastTimestamp;\n lastDataTimestamp = lastId;\n minSignatures = _REQUIRED_SIGNATURES;\n\n staked = stakingBank.totalSupply();\n uint256 numberOfValidators = 0;\n powers = new uint256[](numberOfValidators);\n validators = new address[](numberOfValidators);\n locations = new string[](numberOfValidators);\n nextLeader = address(0);\n\n unchecked {\n // we will not overflow with timestamp in a lifetime\n nextBlockId = lastId + data.padding + 1;\n }\n }\n\n function getLeaderIndex(uint256, uint256) public pure override returns (uint256) {\n revert NotSupported();\n }\n\n function getLeaderAddressAtTime(uint256) public pure override returns (address) {\n revert NotSupported();\n }\n}\n" + }, + "contracts/interfaces/IBaseChainV1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IBaseChainV1 {\n /// @dev number of blocks (consensus rounds) saved in this contract\n function blocksCount() external returns (uint32);\n\n /// @dev number of all blocks that were generated before switching to this contract\n /// please note, that there might be a gap of one block when we switching from old to new contract\n /// see constructor for details\n function blocksCountOffset() external returns (uint32);\n\n function getLatestBlockId() external view returns (uint32);\n\n function getBlockTimestamp(uint32 _blockId) external view returns (uint32);\n\n function getStatus() external view returns (\n uint256 blockNumber,\n uint16 timePadding,\n uint32 lastDataTimestamp,\n uint32 lastId,\n uint32 nextBlockId\n );\n}\n" + }, + "contracts/interfaces/IRegistry.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\n\ninterface IRegistry {\n event LogRegistered(address indexed destination, bytes32 name);\n\n /// @dev imports new contract addresses and override old addresses, if they exist under provided name\n /// This method can be used for contracts that for some reason do not have `getName` method\n /// @param _names array of contract names that we want to register\n /// @param _destinations array of contract addresses\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external;\n\n /// @dev imports new contracts and override old addresses, if they exist.\n /// Names of contracts are fetched directly from each contract by calling `getName`\n /// @param _destinations array of contract addresses\n function importContracts(address[] calldata _destinations) external;\n\n /// @dev this method ensure, that old and new contract is aware of it state in registry\n /// Note: BSC registry does not have this method. This method was introduced in later stage.\n /// @param _newContract address of contract that will replace old one\n function atomicUpdate(address _newContract) external;\n\n /// @dev similar to `getAddress` but throws when contract name not exists\n /// @param name contract name\n /// @return contract address registered under provided name or throws, if does not exists\n function requireAndGetAddress(bytes32 name) external view returns (address);\n\n /// @param name contract name in a form of bytes32\n /// @return contract address registered under provided name\n function getAddress(bytes32 name) external view returns (address);\n\n /// @param _name contract name\n /// @return contract address assigned to the name or address(0) if not exists\n function getAddressByString(string memory _name) external view returns (address);\n\n /// @dev helper method that converts string to bytes32,\n /// you can use to to generate contract name\n function stringToBytes32(string memory _string) external pure returns (bytes32 result);\n}\n" + }, + "contracts/interfaces/IStakingBank.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IStakingBank is IERC20 {\n /// @param id address of validator wallet\n /// @param location URL of the validator API\n struct Validator {\n address id;\n string location;\n }\n\n event LogValidatorRegistered(address indexed id);\n event LogValidatorUpdated(address indexed id);\n event LogValidatorRemoved(address indexed id);\n event LogMinAmountForStake(uint256 minAmountForStake);\n\n /// @dev setter for `minAmountForStake`\n function setMinAmountForStake(uint256 _minAmountForStake) external;\n\n /// @dev allows to stake `token` by validators\n /// Validator needs to approve StakingBank beforehand\n /// @param _value amount of tokens to stake\n function stake(uint256 _value) external;\n\n /// @dev notification about approval from `_from` address on UMB token\n /// Staking bank will stake max approved amount from `_from` address\n /// @param _from address which approved token spend for IStakingBank\n function receiveApproval(address _from) external returns (bool success);\n\n /// @dev withdraws stake tokens\n /// it throws, when balance will be less than required minimum for stake\n /// to withdraw all use `exit`\n function withdraw(uint256 _value) external returns (bool success);\n\n /// @dev unstake and withdraw all tokens\n function exit() external returns (bool success);\n\n /// @dev creates (register) new validator\n /// @param _id validator address\n /// @param _location location URL of the validator API\n function create(address _id, string calldata _location) external;\n\n /// @dev removes validator\n /// @param _id validator wallet\n function remove(address _id) external;\n\n /// @dev updates validator location\n /// @param _id validator wallet\n /// @param _location new validator URL\n function update(address _id, string calldata _location) external;\n\n /// @return total number of registered validators (with and without balance)\n function getNumberOfValidators() external view returns (uint256);\n\n /// @dev gets validator address for provided index\n /// @param _ix index in array of list of all validators wallets\n function addresses(uint256 _ix) external view returns (address);\n\n /// @param _id address of validator\n /// @return id address of validator\n /// @return location URL of validator\n function validators(address _id) external view returns (address id, string memory location);\n}\n" + }, + "contracts/interfaces/IStakingBankStatic.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./IStakingBank.sol\";\n\n\ninterface IStakingBankStatic is IStakingBank {\n /// @param _validators array of validators addresses to verify\n /// @return TRUE when all validators are valid, FALSE otherwise\n function verifyValidators(address[] calldata _validators) external view returns (bool);\n}\n" + }, + "contracts/interfaces/IUmbrellaFeeds.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IUmbrellaFeeds {\n struct PriceData {\n /// @dev this is placeholder, that can be used for some additional data\n /// atm of creating this smart contract, it is only used as marker for removed data (when == type(uint8).max)\n uint8 data;\n /// @dev heartbeat: how often price data will be refreshed in case price stay flat\n uint24 heartbeat;\n /// @dev timestamp: price time, at this time validators run consensus\n uint32 timestamp;\n /// @dev price\n uint128 price;\n }\n\n struct Signature {\n uint8 v;\n bytes32 r;\n bytes32 s;\n }\n\n /// @dev method for submitting consensus data\n /// @param _priceKeys array of keys for `_priceDatas`\n /// @param _priceDatas PriceData signed by validators\n /// @param _signatures validators signatures\n function update(\n bytes32[] calldata _priceKeys,\n PriceData[] calldata _priceDatas,\n Signature[] calldata _signatures\n ) external;\n\n /// @dev it will return array of price datas for provided `_keys`\n /// In case ony of feed does not exist, fallback call will be executed for that feed.\n /// @notice If data for any key not exists, function will revert. Use `getManyPriceDataRaw` method if you don't\n /// want revert.\n /// @param _keys array of feed keys\n /// @return data PriceData array\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data);\n\n /// @dev same as getManyPriceData() but does not revert on empty data.\n /// @notice This method does no revert if some data does not exists.\n /// Check `data.timestamp` to see if price exist, if it is 0, then it does not exist.\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data);\n\n /// @dev this is main endpoint for reading feeds.\n /// In case timestamp is empty (that means there is no data), contract will revert.\n /// If you do not need whole data from `PriceData` struct, you can save some gas by using other view methods that\n /// returns just what you need.\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return data full PriceData struct\n function getPriceData(bytes32 _key) external view returns (PriceData memory data);\n\n /// @notice reader for mapping\n /// @param _key hash of feed name\n /// @return data full PriceData struct\n function prices(bytes32 _key) external view returns (PriceData memory data);\n\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return price\n function getPrice(bytes32 _key) external view returns (uint128 price);\n\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return price\n /// @return timestamp\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp);\n\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return price\n /// @return timestamp\n /// @return heartbeat\n function getPriceTimestampHeartbeat(bytes32 _key)\n external\n view\n returns (uint128 price, uint32 timestamp, uint24 heartbeat);\n\n /// @dev This method should be used only for Layer2 as it is more gas consuming than others views.\n /// @notice It does not revert on empty data.\n /// @param _name string feed name\n /// @return data PriceData\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data);\n\n /// @dev decimals for prices stored in this contract\n function DECIMALS() external view returns (uint8); // solhint-disable-line func-name-mixedcase\n}\n" + }, + "contracts/interfaces/StakingBankStaticNotSupported.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./IStakingBank.sol\";\n\nabstract contract StakingBankStaticNotSupported is IStakingBank {\n error NotSupported();\n\n function create(address, string calldata) external pure {\n revert NotSupported();\n }\n\n function update(address, string calldata) external pure {\n revert NotSupported();\n }\n\n function remove(address) external pure {\n revert NotSupported();\n }\n\n function transfer(address, uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function transferFrom(address, address, uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function receiveApproval(address) external pure returns (bool) {\n revert NotSupported();\n }\n\n function allowance(address, address) external pure returns (uint256) {\n revert NotSupported();\n }\n\n function approve(address, uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function stake(uint256) external pure {\n revert NotSupported();\n }\n\n function withdraw(uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function exit() external pure returns (bool) {\n revert NotSupported();\n }\n\n function setMinAmountForStake(uint256) external pure {\n revert NotSupported();\n }\n}\n" + }, + "contracts/mock/Distributor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport \"../Registry.sol\";\n\ncontract Distributor is Ownable {\n address[] public recipients;\n uint256 public bottomLimit = 5e17;\n uint256 public topLimit = 1e18;\n\n constructor(address[] memory _recipients) {\n recipients = _recipients;\n }\n\n receive() external payable {\n distribute();\n }\n\n function setLimits(uint256 _bottom, uint256 _top) external onlyOwner {\n bottomLimit = _bottom;\n topLimit = _top;\n }\n\n function withdraw() external {\n uint balance = address(this).balance;\n uint buffer = recipients.length * (topLimit - bottomLimit);\n\n if (balance > buffer) {\n payable(owner()).transfer(balance - buffer);\n }\n }\n\n function addRecipients(address[] calldata _recipients) external onlyOwner {\n for (uint256 i = 0; i < _recipients.length; i++) {\n recipients.push(_recipients[i]);\n }\n }\n\n function removeRecipient(address _recipient) external onlyOwner {\n for (uint256 i = 0; i < recipients.length; i++) {\n if (recipients[i] == _recipient) {\n recipients[i] = recipients[recipients.length - 1];\n recipients.pop();\n return;\n }\n }\n }\n\n function recipientsCount() external view returns (uint256) {\n return recipients.length;\n }\n\n function allRecipients() external view returns (address[] memory) {\n return recipients;\n }\n\n function getName() external pure returns (bytes32) {\n return \"Distributor\";\n }\n\n function distribute() public {\n uint256 limit = bottomLimit;\n uint256 top = topLimit;\n uint256 count = recipients.length;\n uint256 totalBalance = address(this).balance;\n\n for (uint256 i = 0; i < count; i++) {\n uint256 balance = recipients[i].balance;\n\n if (balance > limit) {\n continue;\n }\n\n uint256 amount = top - balance > totalBalance ? totalBalance : top - balance;\n\n if (amount > 0) {\n payable(recipients[i]).transfer(amount);\n totalBalance -= amount;\n }\n }\n }\n}\n" + }, + "contracts/mock/LimitedMintingToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\ncontract LimitedMintingToken is ERC20, Ownable {\n struct MintData {\n uint256 dailyAllowance;\n mapping (address => uint256) lastMintTimestamp;\n mapping (address => uint256) todaysMintedAmount;\n }\n\n MintData public mintData;\n\n constructor(string memory _name, string memory _symbol, uint256 _dailyAllowance) ERC20(_name, _symbol) {\n mintData.dailyAllowance = _dailyAllowance;\n }\n\n function mint(address _holder, uint256 _amount) external {\n MintData storage data = mintData;\n\n (uint256 limit, bool fullLimit) = _currentLimit(data);\n\n require(limit > 0, \"This address already claimed the maximum daily amount\");\n\n uint256 lastTimestamp = data.lastMintTimestamp[msg.sender];\n uint256 mintedAmount = data.todaysMintedAmount[msg.sender];\n\n uint256 amount = _amount > limit ? limit : _amount;\n data.lastMintTimestamp[msg.sender] = fullLimit ? block.timestamp : lastTimestamp;\n data.todaysMintedAmount[msg.sender] = fullLimit ? amount : mintedAmount + amount;\n\n _mint(_holder, amount);\n }\n\n function mintApproveAndStake(IStakingBank _stakingBank, address _holder, uint256 _amount) external {\n _mint(_holder, _amount);\n _approve(_holder, address(_stakingBank), _amount);\n _stakingBank.receiveApproval(_holder);\n }\n\n function getDailyAllowance() external view returns (uint256) {\n return mintData.dailyAllowance;\n }\n\n function getName() external pure returns (bytes32) {\n return \"UMB\";\n }\n\n function setDailyAllowance(uint256 newDailyAllowance) public onlyOwner {\n MintData storage data = mintData;\n data.dailyAllowance = newDailyAllowance;\n }\n\n function _currentLimit(MintData storage data) internal view returns (uint256 limit, bool fullLimit) {\n uint256 lastMint = data.lastMintTimestamp[msg.sender];\n fullLimit = block.timestamp - lastMint >= 24 hours;\n\n uint256 usedLimit = data.todaysMintedAmount[msg.sender];\n\n limit = fullLimit ? data.dailyAllowance : data.dailyAllowance - usedLimit;\n }\n}\n" + }, + "contracts/mock/Token.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\n// please remember this is our dummy token!\n// it will be replaced by proper DPoS solution in future\ncontract Token is ERC20 {\n constructor(\n string memory _name,\n string memory _symbol) ERC20(_name, _symbol) {\n }\n\n function mint(address _holder, uint256 _amount) external {\n _mint(_holder, _amount);\n }\n\n function mintApproveAndStake(IStakingBank _stakingBank, address _holder, uint256 _amount) external {\n _mint(_holder, _amount);\n _approve(_holder, address(_stakingBank), _amount);\n _stakingBank.receiveApproval(_holder);\n }\n\n function getName() external pure returns (bytes32) {\n return \"UMB\";\n }\n}\n" + }, + "contracts/onChainFeeds/UmbrellaFeeds.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/IUmbrellaFeeds.sol\";\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IStakingBankStatic.sol\";\n\n/// @dev Main contract for all on-chain data.\n/// Check `UmbrellaFeedsReader` to see how to integrate.\n///\n/// @notice This contract can be destroyed and replaced with new one (with new address).\n/// For best gas efficiency you should pick one of two ways of integration:\n/// 1. make `UmbrellaFeeds` immutable and use fallback in case of selfdestruct. After new deployment, it is recommended\n/// to update address to avoid fallback and reduce gas cost to minimum. In long run this is most efficient solution,\n/// better than any proxy.\n/// 2. always check newest `UmbrellaFeeds` via `Regostry` and fallback will not be needed.\ncontract UmbrellaFeeds is IUmbrellaFeeds {\n bytes constant public ETH_PREFIX = \"\\x19Ethereum Signed Message:\\n32\";\n string constant public NAME = \"UmbrellaFeeds\";\n\n /// @dev deployment time, used for protect for unintentional destroy\n uint256 public immutable DEPLOYED_AT; // solhint-disable-line var-name-mixedcase\n\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\n /// resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev StakingBank contract where list of validators is stored\n IStakingBankStatic public immutable STAKING_BANK; // solhint-disable-line var-name-mixedcase\n\n /// @dev minimal number of signatures required for accepting price submission (PoA)\n uint16 public immutable REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\n\n /// @dev decimals for prices stored in this contract\n uint8 public immutable DECIMALS; // solhint-disable-line var-name-mixedcase\n\n /// @notice map of all prices stored in this contract, key for map is hash of feed name\n /// eg for \"ETH-USD\" feed, key will be hash(\"ETH-USD\")\n mapping (bytes32 => PriceData) private _prices;\n\n error ArraysDataDoNotMatch();\n error FeedNotExist();\n error NotEnoughSignatures();\n error InvalidSigner();\n error InvalidRequiredSignatures();\n error SignaturesOutOfOrder();\n error ECDSAInvalidSignatureS();\n error ECDSAInvalidSignatureV();\n error OldData();\n error ContractInUse();\n error ContractNotInitialised();\n\n /// @param _contractRegistry Registry address\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n /// @param _decimals decimals for prices stored in this contract\n constructor(\n IRegistry _contractRegistry,\n uint16 _requiredSignatures,\n uint8 _decimals\n ) {\n if (_requiredSignatures == 0) revert InvalidRequiredSignatures();\n\n REGISTRY = _contractRegistry;\n REQUIRED_SIGNATURES = _requiredSignatures;\n STAKING_BANK = IStakingBankStatic(_contractRegistry.requireAndGetAddress(\"StakingBank\"));\n DECIMALS = _decimals;\n DEPLOYED_AT = block.timestamp;\n }\n\n /// @dev destroys old contract\n /// there is sanity check that prevents abuse of destroy method\n /// @param _name string feed key to verify, that contract was initialised\n function destroy(string calldata _name) external {\n if (REGISTRY.getAddressByString(NAME) == address(this)) revert ContractInUse();\n\n if (_prices[keccak256(abi.encodePacked(_name))].timestamp == 0 && DEPLOYED_AT + 3 days > block.timestamp) {\n revert ContractNotInitialised();\n }\n\n selfdestruct(payable(msg.sender));\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function update(\n bytes32[] calldata _priceKeys,\n PriceData[] calldata _priceDatas,\n Signature[] calldata _signatures\n ) external {\n if (_priceKeys.length != _priceDatas.length) revert ArraysDataDoNotMatch();\n\n bytes32 priceDataHash = keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n verifySignatures(priceDataHash, _signatures);\n\n uint256 i;\n\n while (i < _priceDatas.length) {\n bytes32 priceKey = _priceKeys[i];\n\n // we do not allow for older prices\n // at the same time it prevents from reusing signatures\n if (_prices[priceKey].timestamp >= _priceDatas[i].timestamp) revert OldData();\n\n _prices[priceKey] = _priceDatas[i];\n\n // atm there is no need for events, so in order to save gas, we do not emit any\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n if (data[i].timestamp == 0) revert FeedNotExist();\n\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function prices(bytes32 _key) external view returns (PriceData memory data) {\n data = _prices[_key];\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceData(bytes32 _key) external view returns (PriceData memory data) {\n data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPrice(bytes32 _key) external view returns (uint128 price) {\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return data.price;\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp) {\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp);\n }\n\n function getPriceTimestampHeartbeat(bytes32 _key)\n external\n view\n returns (uint128 price, uint32 timestamp, uint24 heartbeat)\n {\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp, data.heartbeat);\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data) {\n bytes32 key = keccak256(abi.encodePacked(_name));\n data = _prices[key];\n }\n\n /// @dev helper method for QA purposes\n /// @return hash of data that are signed by validators (keys and priced data)\n function hashData(bytes32[] calldata _priceKeys, PriceData[] calldata _priceDatas)\n external\n view\n returns (bytes32)\n {\n return keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n }\n\n /// @param _hash hash of signed data\n /// @param _signatures array of validators signatures\n function verifySignatures(bytes32 _hash, Signature[] calldata _signatures) public view {\n address prevSigner = address(0x0);\n\n if (_signatures.length < REQUIRED_SIGNATURES) revert NotEnoughSignatures();\n\n address[] memory validators = new address[](REQUIRED_SIGNATURES);\n\n // to save gas we check only required number of signatures\n // case, where you can have part of signatures invalid but still enough valid in total is not supported\n for (uint256 i; i < REQUIRED_SIGNATURES;) {\n (uint8 v, bytes32 r, bytes32 s) = (_signatures[i].v, _signatures[i].r, _signatures[i].s);\n\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n revert ECDSAInvalidSignatureS();\n }\n\n if (uint8(v) != 27 && uint8(v) != 28) revert ECDSAInvalidSignatureV();\n\n address signer = recoverSigner(_hash, v, r, s);\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\n\n // because we check only required number of signatures, any invalid one will cause revert\n prevSigner = signer;\n validators[i] = signer;\n\n unchecked { i++; }\n }\n\n // bulk verification can optimise gas when we have 5 or more validators\n if (!STAKING_BANK.verifyValidators(validators)) revert InvalidSigner();\n }\n\n function getChainId() public view returns (uint256 id) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n id := chainid()\n }\n }\n\n /// @param _hash hashed of data\n /// @param _v part of signature\n /// @param _r part of signature\n /// @param _s part of signature\n /// @return signer address\n function recoverSigner(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _hash));\n return ecrecover(hash, _v, _r, _s);\n }\n\n /// @dev to follow Registrable interface\n function getName() public pure returns (bytes32) {\n return \"UmbrellaFeeds\";\n }\n}\n" + }, + "contracts/onChainFeeds/UmbrellaFeedsReader.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IUmbrellaFeeds.sol\";\n\n/// @dev This is optional price reader for just one feed.\n/// It comes with chanilink interface that makes migration process easier.\n/// For maximum gas optimisation it is recommended to use UmbrellaFeeds directly - simply follow this contract as\n/// a guide for integration.\n///\n/// This contract has build in fallback feature in case, `UmbrellaFeeds` will be replaced by newer contract.\n/// Fallback is transparent for the user, no additional setup is needed.\n///\n/// How fallback feature works? If data for provided key is empty (when UmbrellaFeeds was destroyed and replaced),\n/// contract will execute following procedure:\n/// 1. if data is empty, contract will check if there is new registered contract with requested data\n/// 2. if data is found in new contract it will be returned\n/// 3. if there is no data or there is no new contract tx will revert.\ncontract UmbrellaFeedsReader {\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\n /// resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev contract where all the feeds are stored\n address public immutable UMBRELLA_FEEDS; // solhint-disable-line var-name-mixedcase\n\n /// @dev key (hash of string key), under which feed is being stored\n bytes32 public immutable KEY; // solhint-disable-line var-name-mixedcase\n\n /// @dev string representation of feed key (feed name)\n string public description;\n\n /// @dev decimals for feed\n uint8 internal immutable _DECIMALS; // solhint-disable-line var-name-mixedcase\n\n error EmptyAddress();\n error FeedNotExist();\n\n /// @param _registry IRegistry address\n /// @param _umbrellaFeeds UmbrellaFeeds address\n /// @param _key price data key (before hashing)\n constructor(IRegistry _registry, IUmbrellaFeeds _umbrellaFeeds, string memory _key) {\n if (address(_registry) == address(0)) revert EmptyAddress();\n\n REGISTRY = _registry;\n UMBRELLA_FEEDS = address(_umbrellaFeeds);\n description = _key;\n _DECIMALS = _umbrellaFeeds.DECIMALS();\n\n bytes32 hash = keccak256(abi.encodePacked(_key));\n KEY = hash;\n\n // sanity check\n _umbrellaFeeds.getPriceData(hash);\n }\n\n /// @dev decimals for feed\n function decimals() external view returns (uint8) {\n return _DECIMALS;\n }\n\n /// @dev this method follows chainlink interface for easy migration, NOTE: not all returned data are covered!\n /// latestRoundData() raise exception when there is no data, instead of returning unset values,\n /// which could be misinterpreted as actual reported values.\n /// It DOES NOT raise when data is outdated (based on heartbeat and timestamp).\n /// @notice You can save some gas by doing call directly to `UMBRELLA_FEEDS` contract.\n /// @return uint80 originally `roundId`, not in use, always 0\n /// @return answer price\n /// @return uint256 originally `startedAt`, not in use, always 0\n /// @return updatedAt last timestamp data was updated\n /// @return uint80 originally `answeredInRound` not in use, always 0\n function latestRoundData()\n external\n view\n returns (\n uint80 /* roundId */,\n int256 answer,\n uint256 /* startedAt */,\n uint256 updatedAt,\n uint80 /* answeredInRound */\n )\n {\n IUmbrellaFeeds.PriceData memory priceData = _getPriceDataRaw();\n\n if (priceData.timestamp == 0) {\n priceData = _fallbackCall();\n }\n\n return (0, int256(uint256(priceData.price)), 0, priceData.timestamp, 0);\n }\n\n /// @dev this is main endpoint for reading feed. Feed is read from UmbrellaFeeds contract using hardcoded `KEY`.\n /// In case timestamp is empty (that means there is no data), contract will execute fallback call.\n /// @notice revert on empty data\n function getPriceData() external view returns (IUmbrellaFeeds.PriceData memory priceData) {\n priceData = _getPriceDataRaw();\n\n if (priceData.timestamp == 0) {\n priceData = _fallbackCall();\n }\n }\n\n /// @dev same as `getPriceData` but does not revert when no data\n function getPriceDataRaw() external view returns (IUmbrellaFeeds.PriceData memory priceData) {\n priceData = _getPriceDataRaw();\n\n if (priceData.timestamp == 0) {\n return _fallbackCallRaw();\n }\n }\n\n /// @dev same as `getPriceData` but does not revert when no data\n function _getPriceDataRaw() internal view returns (IUmbrellaFeeds.PriceData memory priceData) {\n (bool success, bytes memory data) = UMBRELLA_FEEDS.staticcall(\n abi.encodeWithSelector(IUmbrellaFeeds.prices.selector, KEY)\n );\n\n if (success && data.length != 0) {\n priceData = abi.decode(data, (IUmbrellaFeeds.PriceData));\n }\n }\n\n /// @dev it will revert on empty data\n function _fallbackCall() internal view returns (IUmbrellaFeeds.PriceData memory data) {\n address umbrellaFeeds = REGISTRY.getAddressByString(\"UmbrellaFeeds\");\n\n // if contract was NOT updated, fallback is not needed, data does not exist - revert\n if (umbrellaFeeds == UMBRELLA_FEEDS) revert FeedNotExist();\n\n data = IUmbrellaFeeds(umbrellaFeeds).getPriceData(KEY);\n }\n\n /// @dev it will not revert on empty data\n function _fallbackCallRaw() internal view returns (IUmbrellaFeeds.PriceData memory data) {\n address umbrellaFeeds = REGISTRY.getAddressByString(\"UmbrellaFeeds\");\n\n // if contract was updated, we do fallback\n if (umbrellaFeeds != UMBRELLA_FEEDS) {\n data = IUmbrellaFeeds(umbrellaFeeds).prices(KEY);\n }\n }\n}\n" + }, + "contracts/onChainFeeds/UmbrellaFeedsReaderFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\nimport \"./UmbrellaFeedsReader.sol\";\n\n/// @notice Factory to deploy UmbrellaFeedsReader contract\ncontract UmbrellaFeedsReaderFactory {\n /// @dev Registry contract where list of all addresses is stored. Used to resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev list of all readers\n mapping (bytes32 => UmbrellaFeedsReader) public readers;\n\n event NewUmbrellaFeedsReader(UmbrellaFeedsReader indexed umbrellaFeedsReader, string feedName);\n\n error EmptyAddress();\n\n constructor(IRegistry _registry) {\n if (address(_registry) == address(0)) revert EmptyAddress();\n\n REGISTRY = _registry;\n }\n\n /// @dev Method to deploy new UmbrellaFeedsReader for particular key.\n /// This deployment is optional and it can be done by anyone who needs it.\n /// Reader can be used to simplify migration from Chainlink to Umbrella.\n ///\n /// Check UmbrellaFeedsReader docs for more details.\n ///\n /// We not using minimal proxy because it does not allow for immutable variables.\n /// @param _feedName string Feed name that is registered in UmbrellaFeeds\n /// @return reader UmbrellaFeedsReader contract address, in case anyone wants to use it from Layer1\n function deploy(string memory _feedName) external returns (UmbrellaFeedsReader reader) {\n reader = deployed(_feedName);\n IUmbrellaFeeds umbrellaFeeds = IUmbrellaFeeds(REGISTRY.getAddressByString(\"UmbrellaFeeds\"));\n\n // if UmbrellaFeeds contract is up to date, there is no need to redeploy\n if (address(reader) != address(0) && address(reader.UMBRELLA_FEEDS()) == address(umbrellaFeeds)) {\n return reader;\n }\n\n reader = new UmbrellaFeedsReader(REGISTRY, umbrellaFeeds, _feedName);\n readers[hash(_feedName)] = reader;\n\n emit NewUmbrellaFeedsReader(reader, _feedName);\n }\n\n function deployed(string memory _feedName) public view returns (UmbrellaFeedsReader) {\n return readers[hash(_feedName)];\n }\n\n function hash(string memory _feedName) public pure returns (bytes32) {\n return keccak256(abi.encodePacked(_feedName));\n }\n\n /// @dev to follow Registrable interface\n function getName() public pure returns (bytes32) {\n return \"UmbrellaFeedsReaderFactory\";\n }\n}\n" + }, + "contracts/onChainFeeds/zk-link/UmbrellaFeeds.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../../interfaces/IUmbrellaFeeds.sol\";\nimport \"../../interfaces/IRegistry.sol\";\nimport \"../../interfaces/IStakingBankStatic.sol\";\n\n/// @dev Main contract for all on-chain data.\n/// Check `UmbrellaFeedsReader` to see how to integrate.\n///\n/// @notice This contract can be destroyed and replaced with new one (with new address).\n/// For best gas efficiency you should pick one of two ways of integration:\n/// 1. make `UmbrellaFeeds` immutable and use fallback in case of selfdestruct. After new deployment, it is recommended\n/// to update address to avoid fallback and reduce gas cost to minimum. In long run this is most efficient solution,\n/// better than any proxy.\n/// 2. always check newest `UmbrellaFeeds` via `Regostry` and fallback will not be needed.\ncontract UmbrellaFeeds is IUmbrellaFeeds {\n bytes constant public ETH_PREFIX = \"\\x19Ethereum Signed Message:\\n32\";\n string constant public NAME = \"UmbrellaFeeds\";\n\n /// @dev deployment time, used for protect for unintentional destroy\n uint256 public immutable DEPLOYED_AT; // solhint-disable-line var-name-mixedcase\n\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\n /// resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev StakingBank contract where list of validators is stored\n IStakingBankStatic public immutable STAKING_BANK; // solhint-disable-line var-name-mixedcase\n\n /// @dev minimal number of signatures required for accepting price submission (PoA)\n uint16 public immutable REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\n\n /// @dev decimals for prices stored in this contract\n uint8 public immutable DECIMALS; // solhint-disable-line var-name-mixedcase\n\n /// @dev in case selfdestruct is not supported, this flag will make sure contract is not usable anymore\n bool public disabled;\n\n /// @notice map of all prices stored in this contract, key for map is hash of feed name\n /// eg for \"ETH-USD\" feed, key will be hash(\"ETH-USD\")\n mapping (bytes32 => PriceData) private _prices;\n\n error SelfDestruct();\n error ArraysDataDoNotMatch();\n error FeedNotExist();\n error NotEnoughSignatures();\n error InvalidSigner();\n error InvalidRequiredSignatures();\n error SignaturesOutOfOrder();\n error ECDSAInvalidSignatureS();\n error ECDSAInvalidSignatureV();\n error OldData();\n error ContractInUse();\n error ContractNotInitialised();\n\n /// @param _contractRegistry Registry address\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n /// @param _decimals decimals for prices stored in this contract\n constructor(\n IRegistry _contractRegistry,\n uint16 _requiredSignatures,\n uint8 _decimals\n ) {\n if (_requiredSignatures == 0) revert InvalidRequiredSignatures();\n\n REGISTRY = _contractRegistry;\n REQUIRED_SIGNATURES = _requiredSignatures;\n STAKING_BANK = IStakingBankStatic(_contractRegistry.requireAndGetAddress(\"StakingBank\"));\n DECIMALS = _decimals;\n DEPLOYED_AT = block.timestamp;\n }\n\n /// @dev destroys old contract\n /// there is sanity check that prevents abuse of destroy method\n /// @param _name string feed key to verify, that contract was initialised\n function destroy(string calldata _name) external {\n if (REGISTRY.getAddressByString(NAME) == address(this)) revert ContractInUse();\n\n if (_prices[keccak256(abi.encodePacked(_name))].timestamp == 0 && DEPLOYED_AT + 3 days > block.timestamp) {\n revert ContractNotInitialised();\n }\n\n disabled = true;\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function update(\n bytes32[] calldata _priceKeys,\n PriceData[] calldata _priceDatas,\n Signature[] calldata _signatures\n ) external {\n if (disabled) revert SelfDestruct();\n if (_priceKeys.length != _priceDatas.length) revert ArraysDataDoNotMatch();\n\n bytes32 priceDataHash = keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n verifySignatures(priceDataHash, _signatures);\n\n uint256 i;\n\n while (i < _priceDatas.length) {\n bytes32 priceKey = _priceKeys[i];\n\n // we do not allow for older prices\n // at the same time it prevents from reusing signatures\n if (_prices[priceKey].timestamp >= _priceDatas[i].timestamp) revert OldData();\n\n _prices[priceKey] = _priceDatas[i];\n\n // atm there is no need for events, so in order to save gas, we do not emit any\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n if (disabled) revert SelfDestruct();\n\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n if (data[i].timestamp == 0) revert FeedNotExist();\n\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n if (disabled) revert SelfDestruct();\n\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function prices(bytes32 _key) external view returns (PriceData memory data) {\n if (disabled) revert SelfDestruct();\n\n data = _prices[_key];\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceData(bytes32 _key) external view returns (PriceData memory data) {\n if (disabled) revert SelfDestruct();\n\n data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPrice(bytes32 _key) external view returns (uint128 price) {\n if (disabled) revert SelfDestruct();\n\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return data.price;\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp) {\n if (disabled) revert SelfDestruct();\n\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp);\n }\n\n function getPriceTimestampHeartbeat(bytes32 _key)\n external\n view\n returns (uint128 price, uint32 timestamp, uint24 heartbeat)\n {\n if (disabled) revert SelfDestruct();\n\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp, data.heartbeat);\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data) {\n if (disabled) revert SelfDestruct();\n\n bytes32 key = keccak256(abi.encodePacked(_name));\n data = _prices[key];\n }\n\n /// @dev helper method for QA purposes\n /// @return hash of data that are signed by validators (keys and priced data)\n function hashData(bytes32[] calldata _priceKeys, PriceData[] calldata _priceDatas)\n external\n view\n returns (bytes32)\n {\n return keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n }\n\n /// @param _hash hash of signed data\n /// @param _signatures array of validators signatures\n function verifySignatures(bytes32 _hash, Signature[] calldata _signatures) public view {\n address prevSigner = address(0x0);\n\n if (_signatures.length < REQUIRED_SIGNATURES) revert NotEnoughSignatures();\n\n address[] memory validators = new address[](REQUIRED_SIGNATURES);\n\n // to save gas we check only required number of signatures\n // case, where you can have part of signatures invalid but still enough valid in total is not supported\n for (uint256 i; i < REQUIRED_SIGNATURES;) {\n (uint8 v, bytes32 r, bytes32 s) = (_signatures[i].v, _signatures[i].r, _signatures[i].s);\n\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n revert ECDSAInvalidSignatureS();\n }\n\n if (uint8(v) != 27 && uint8(v) != 28) revert ECDSAInvalidSignatureV();\n\n address signer = recoverSigner(_hash, v, r, s);\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\n\n // because we check only required number of signatures, any invalid one will cause revert\n prevSigner = signer;\n validators[i] = signer;\n\n unchecked { i++; }\n }\n\n // bulk verification can optimise gas when we have 5 or more validators\n if (!STAKING_BANK.verifyValidators(validators)) revert InvalidSigner();\n }\n\n function getChainId() public view returns (uint256 id) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n id := chainid()\n }\n }\n\n /// @param _hash hashed of data\n /// @param _v part of signature\n /// @param _r part of signature\n /// @param _s part of signature\n /// @return signer address\n function recoverSigner(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _hash));\n return ecrecover(hash, _v, _r, _s);\n }\n\n /// @dev to follow Registrable interface\n function getName() public pure returns (bytes32) {\n return \"UmbrellaFeeds\";\n }\n}\n" + }, + "contracts/Registry.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\n// Inheritance\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport \"./extensions/Registrable.sol\";\nimport \"./interfaces/IRegistry.sol\";\n\n/// @dev contracts registry\n/// protocol uses this registry to fetch current contract addresses\ncontract Registry is IRegistry, Ownable {\n /// name => contract address\n mapping(bytes32 => address) public registry;\n\n\n error NameNotRegistered();\n error ArraysDataDoNotMatch();\n\n /// @inheritdoc IRegistry\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external onlyOwner {\n if (_names.length != _destinations.length) revert ArraysDataDoNotMatch();\n\n for (uint i = 0; i < _names.length;) {\n registry[_names[i]] = _destinations[i];\n emit LogRegistered(_destinations[i], _names[i]);\n\n unchecked {\n i++;\n }\n }\n }\n\n /// @inheritdoc IRegistry\n function importContracts(address[] calldata _destinations) external onlyOwner {\n for (uint i = 0; i < _destinations.length;) {\n bytes32 name = Registrable(_destinations[i]).getName();\n registry[name] = _destinations[i];\n emit LogRegistered(_destinations[i], name);\n\n unchecked {\n i++;\n }\n }\n }\n\n /// @inheritdoc IRegistry\n function atomicUpdate(address _newContract) external onlyOwner {\n Registrable(_newContract).register();\n\n bytes32 name = Registrable(_newContract).getName();\n address oldContract = registry[name];\n registry[name] = _newContract;\n\n Registrable(oldContract).unregister();\n\n emit LogRegistered(_newContract, name);\n }\n\n /// @inheritdoc IRegistry\n function requireAndGetAddress(bytes32 name) external view returns (address) {\n address _foundAddress = registry[name];\n if (_foundAddress == address(0)) revert NameNotRegistered();\n\n return _foundAddress;\n }\n\n /// @inheritdoc IRegistry\n function getAddress(bytes32 _bytes) external view returns (address) {\n return registry[_bytes];\n }\n\n /// @inheritdoc IRegistry\n function getAddressByString(string memory _name) public view returns (address) {\n return registry[stringToBytes32(_name)];\n }\n\n /// @inheritdoc IRegistry\n function stringToBytes32(string memory _string) public pure returns (bytes32 result) {\n bytes memory tempEmptyStringTest = bytes(_string);\n\n if (tempEmptyStringTest.length == 0) {\n return 0x0;\n }\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n result := mload(add(_string, 32))\n }\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStatic.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/StakingBankStaticNotSupported.sol\";\n\n/// @dev Because we are using PoA in UMB oracle, staked balance does not matter. What's matter is, if signer is\n/// validator or not. In this case we can optimise `StakingBank` and make it static for better gas performance.\nabstract contract StakingBankStatic is StakingBankStaticNotSupported {\n uint256 public constant ONE = 1e18;\n\n uint256 public immutable NUMBER_OF_VALIDATORS; // solhint-disable-line var-name-mixedcase\n uint256 public immutable TOTAL_SUPPLY; // solhint-disable-line var-name-mixedcase\n\n constructor(uint256 _validatorsCount) {\n NUMBER_OF_VALIDATORS = _validatorsCount;\n TOTAL_SUPPLY = _validatorsCount * ONE;\n\n _assertValidSetup(_validatorsCount);\n }\n\n function balances(address _validator) external view returns (uint256) {\n return _isValidator(_validator) ? ONE : 0;\n }\n\n function verifyValidators(address[] calldata _validators) external view returns (bool) {\n for (uint256 i; i < _validators.length;) {\n if (!_isValidator(_validators[i])) return false;\n unchecked { i++; }\n }\n\n return true;\n }\n\n function getNumberOfValidators() external view returns (uint256) {\n return NUMBER_OF_VALIDATORS;\n }\n\n function getAddresses() external view returns (address[] memory) {\n return _addresses();\n }\n\n function getBalances() external view returns (uint256[] memory allBalances) {\n allBalances = new uint256[](NUMBER_OF_VALIDATORS);\n\n for (uint256 i; i < NUMBER_OF_VALIDATORS;) {\n allBalances[i] = ONE;\n\n unchecked {\n // we will not have enough data to overflow\n i++;\n }\n }\n }\n\n function addresses(uint256 _ix) external view returns (address) {\n return _addresses()[_ix];\n }\n\n function validators(address _id) external view virtual returns (address id, string memory location);\n\n /// @dev to follow ERC20 interface\n function balanceOf(address _account) external view returns (uint256) {\n return _isValidator(_account) ? ONE : 0;\n }\n\n /// @dev to follow ERC20 interface\n function totalSupply() external view returns (uint256) {\n return TOTAL_SUPPLY;\n }\n\n /// @dev to follow Registrable interface\n function getName() external pure returns (bytes32) {\n return \"StakingBank\";\n }\n\n /// @dev to follow Registrable interface\n function register() external pure {\n // there are no requirements atm\n }\n\n /// @dev to follow Registrable interface\n function unregister() external pure {\n // there are no requirements atm\n }\n\n function _addresses() internal view virtual returns (address[] memory);\n\n function _isValidator(address _validator) internal view virtual returns (bool);\n\n function _assertValidSetup(uint256 _validatorsCount) internal view virtual{\n address[] memory list = _addresses();\n require(list.length == _validatorsCount);\n\n for (uint256 i; i < _validatorsCount;) {\n require(_isValidator(list[i]));\n\n unchecked { i ++; }\n }\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticCI.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticCI is StakingBankStatic {\n // 0x87630b2d1de0fbd5044eb6891b3d9d98c34c8d310c852f98550ba774480e47cc\n address public constant VALIDATOR_0 = 0x2fFd013AaA7B5a7DA93336C2251075202b33FB2B;\n // 0x3f1e8b94c70206bf816c1ed0b15ad98bdf225ae4c6e7e4eee6cdbcf706fda2ae\n address public constant VALIDATOR_1 = 0x43158ea338Ff13D0bDa0c3EB969B9EA5a624E7Cc;\n // 0x5da6b84117504d06b5dcd52b990d76965d2882f4e5852eb610bc76e4209b10d7\n address public constant VALIDATOR_2 = 0x9Fd8DD0627b9A32399Fd115c4725C7e17BC40e6d;\n // 0x1e5012671de3332ad0b43661984e94ab0e405bffddc9d3e863055040bab354b8\n address public constant VALIDATOR_3 = 0xa3F3659E469b7aE0b249546338DEdc0b684edB05;\n // 0x0edc1e35ea7701ddac703286674e79f04addbf5d2f6162fabc19d39bd3dc6662\n address public constant VALIDATOR_4 = 0xB98A954B9036DF144d685E910bfbAEC6B33A8d11;\n // 0x23c601ae397441f3ef6f1075dcb0031ff17fb079837beadaf3c84d96c6f3e569\n address public constant VALIDATOR_5 = 0xE5904695748fe4A84b40b3fc79De2277660BD1D3;\n\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.ci.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.ci.umb.network\");\n if (_id == VALIDATOR_2) return (_id, \"https://validator3.ci.umb.network\");\n if (_id == VALIDATOR_3) return (_id, \"https://validator4.ci.umb.network\");\n if (_id == VALIDATOR_4) return (_id, \"https://validator5.ci.umb.network\");\n if (_id == VALIDATOR_5) return (_id, \"https://validator6.ci.umb.network\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n list[2] = VALIDATOR_2;\n list[3] = VALIDATOR_3;\n list[4] = VALIDATOR_4;\n list[5] = VALIDATOR_5;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0\n || _validator == VALIDATOR_1\n || _validator == VALIDATOR_2\n || _validator == VALIDATOR_3\n || _validator == VALIDATOR_4\n || _validator == VALIDATOR_5\n );\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticDev.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticDev is StakingBankStatic {\n address public constant VALIDATOR_0 = 0xDc3eBc37DA53A644D67E5E3b5BA4EEF88D969d5C;\n address public constant VALIDATOR_1 = 0x998cb7821e605cC16b6174e7C50E19ADb2Dd2fB0;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.dev.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.dev.umb.network\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0 || _validator == VALIDATOR_1);\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticLocal.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticLocal is StakingBankStatic {\n address public constant VALIDATOR_0 = 0xeAD9C93b79Ae7C1591b1FB5323BD777E86e150d4;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"localhost\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0);\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticProd.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\ncontract StakingBankStaticProd is StakingBankStatic {\n address public constant VALIDATOR_0 = 0x977Ba523420110e230643B772Fe9cF955e11dA7B;\n address public constant VALIDATOR_1 = 0xe2422b23e52bc13ebA04d7FbB9F332Deb43360fB;\n\n // external order is based on validators submits on AVAX for Apr 2023\n address public constant VALIDATOR_2 = 0x57F404aD75e371c1A539589C1eFCA12e0C6980AD;\n address public constant VALIDATOR_3 = 0xD56C6A4f64E0bD70260472d1DB6Cf5825858CB0d;\n address public constant VALIDATOR_4 = 0x93FdcAB283b0BcAc48157590af482E1CFd6af6aC;\n address public constant VALIDATOR_5 = 0xCd733E06B06083d52fC5867E8E3432aA5c103A38;\n address public constant VALIDATOR_6 = 0x42e210b110c6aa49CdfA7ceF1444Aa4719653111;\n address public constant VALIDATOR_7 = 0x501731c6a69803a53Ec6c3e12f293c247cE1092B;\n address public constant VALIDATOR_8 = 0x8bF9661F1b247522C75DD0FE84355aD2EfF27144;\n address public constant VALIDATOR_9 = 0x281754Ab58391A478B7aA4E7f39991CfB41118c4;\n address public constant VALIDATOR_10 = 0x57A51D5BDcE188c2295fCA3b4687475a54E65A02;\n address public constant VALIDATOR_11 = 0x2F85824B2B38F179E451988670935d315b5b9692;\n address public constant VALIDATOR_12 = 0xA7241994267682de4dE7Ef62f52dc2C783d1784B;\n address public constant VALIDATOR_13 = 0x6eEd457C20603EDAE50C3A112CAA1a9425321bD0;\n address public constant VALIDATOR_14 = 0xC5a7650c2725a7B6A39f15cb9FbffC7af357AFeb;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n // solhint-disable-next-line code-complexity\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.umb.network\");\n if (_id == VALIDATOR_2) return (_id, \"https://umbrella.artemahr.tech\");\n if (_id == VALIDATOR_3) return (_id, \"https://umb.vtabsolutions.com:3030\");\n if (_id == VALIDATOR_4) return (_id, \"https://umbrella.crazywhale.es\");\n if (_id == VALIDATOR_5) return (_id, \"https://umbrella-node.gateomega.com\");\n if (_id == VALIDATOR_6) return (_id, \"https://umb.anorak.technology\");\n if (_id == VALIDATOR_7) return (_id, \"https://umbrella.validator.infstones.io\");\n if (_id == VALIDATOR_8) return (_id, \"https://umb.hashkey.cloud\");\n if (_id == VALIDATOR_9) return (_id, \"http://umbrella.staking4all.org:3000\");\n if (_id == VALIDATOR_10) return (_id, \"http://5.161.78.230:3000\");\n if (_id == VALIDATOR_11) return (_id, \"https://umb-api.staking.rocks\");\n if (_id == VALIDATOR_12) return (_id, \"https://rpc.urbanhq.net\");\n if (_id == VALIDATOR_13) return (_id, \"https://umbrella-node.ankastake.com\");\n if (_id == VALIDATOR_14) return (_id, \"https://umbrella.tchambrella.com\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n list[2] = VALIDATOR_2;\n list[3] = VALIDATOR_3;\n list[4] = VALIDATOR_4;\n list[5] = VALIDATOR_5;\n list[6] = VALIDATOR_6;\n list[7] = VALIDATOR_7;\n list[8] = VALIDATOR_8;\n list[9] = VALIDATOR_9;\n list[10] = VALIDATOR_10;\n list[11] = VALIDATOR_11;\n list[12] = VALIDATOR_12;\n list[13] = VALIDATOR_13;\n list[14] = VALIDATOR_14;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (\n _validator == VALIDATOR_0\n || _validator == VALIDATOR_1\n || _validator == VALIDATOR_2\n || _validator == VALIDATOR_3\n || _validator == VALIDATOR_4\n || _validator == VALIDATOR_5\n || _validator == VALIDATOR_6\n || _validator == VALIDATOR_7\n || _validator == VALIDATOR_8\n || _validator == VALIDATOR_9\n || _validator == VALIDATOR_10\n || _validator == VALIDATOR_11\n || _validator == VALIDATOR_12\n || _validator == VALIDATOR_13\n || _validator == VALIDATOR_14\n );\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticSbx.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticSbx is StakingBankStatic {\n address public constant VALIDATOR_0 = 0xE3bDa0C6E1fBB111091Dfef6f22a673b20Ea5F50;\n address public constant VALIDATOR_1 = 0xc1773490F00963CBAb3841fc07C1a0796E658Ba2;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.sbx.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.sbx.umb.network\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0 || _validator == VALIDATOR_1);\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": false, + "runs": 0 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/eth_production/ForeignChain.json b/deployments/eth_production/ForeignChain.json index d68d76f2..55f1b014 100644 --- a/deployments/eth_production/ForeignChain.json +++ b/deployments/eth_production/ForeignChain.json @@ -1,5 +1,5 @@ { - "address": "0xCA799ca83e85848c76b39679DBb5af49884A2578", + "address": "0xFB72B4BE9e57B85561F69D26aeBD2286feA13c36", "abi": [ { "inputs": [ @@ -1051,47 +1051,47 @@ "type": "function" } ], - "transactionHash": "0x17c322e49ef6e5077a46b900554fcadec9ed04f4af0ea08b3fe3aaa7570e87ff", + "transactionHash": "0x86fa0f409f03d34c5147cadaac41bd1286823c556810e52266a2e1cfc11697c6", "receipt": { "to": null, "from": "0xA6e4fFa19B213AbeA258ae72e8e1a209B9E543e7", - "contractAddress": "0xCA799ca83e85848c76b39679DBb5af49884A2578", - "transactionIndex": 74, + "contractAddress": "0xFB72B4BE9e57B85561F69D26aeBD2286feA13c36", + "transactionIndex": 8, "gasUsed": "4445421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000800000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000020400040000000000000000020000000000000000000000000000002000000000000000000000000000000000000000000000000008000000000010000000000000400000000000000000000000000000000000020000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xb425a74b555df57d73ecd58a913856ba672af0d7cc576dac39c4124264e30d7a", - "transactionHash": "0x17c322e49ef6e5077a46b900554fcadec9ed04f4af0ea08b3fe3aaa7570e87ff", + "logsBloom": "0x00000004000000000000000000000000000000000000000000800000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000200000000000000000000000020400000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000010000000000000400000000000000000000000000000001000020000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x6b5f1020add0d027b83ccb47f6d467eab22419428e26d10721e1a1c42a771592", + "transactionHash": "0x86fa0f409f03d34c5147cadaac41bd1286823c556810e52266a2e1cfc11697c6", "logs": [ { - "transactionIndex": 74, - "blockNumber": 18519594, - "transactionHash": "0x17c322e49ef6e5077a46b900554fcadec9ed04f4af0ea08b3fe3aaa7570e87ff", - "address": "0xCA799ca83e85848c76b39679DBb5af49884A2578", + "transactionIndex": 8, + "blockNumber": 21078154, + "transactionHash": "0x86fa0f409f03d34c5147cadaac41bd1286823c556810e52266a2e1cfc11697c6", + "address": "0xFB72B4BE9e57B85561F69D26aeBD2286feA13c36", "topics": [ "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x000000000000000000000000a6e4ffa19b213abea258ae72e8e1a209b9e543e7" ], "data": "0x", - "logIndex": 182, - "blockHash": "0xb425a74b555df57d73ecd58a913856ba672af0d7cc576dac39c4124264e30d7a" + "logIndex": 92, + "blockHash": "0x6b5f1020add0d027b83ccb47f6d467eab22419428e26d10721e1a1c42a771592" }, { - "transactionIndex": 74, - "blockNumber": 18519594, - "transactionHash": "0x17c322e49ef6e5077a46b900554fcadec9ed04f4af0ea08b3fe3aaa7570e87ff", - "address": "0xCA799ca83e85848c76b39679DBb5af49884A2578", + "transactionIndex": 8, + "blockNumber": 21078154, + "transactionHash": "0x86fa0f409f03d34c5147cadaac41bd1286823c556810e52266a2e1cfc11697c6", + "address": "0xFB72B4BE9e57B85561F69D26aeBD2286feA13c36", "topics": [ "0x02ff77a0f68d11f7efb906f331b2dda82916de8ba9c37dda2a95817936a530ec", "0x000000000000000000000000a6e4ffa19b213abea258ae72e8e1a209b9e543e7" ], "data": "0x000000000000000000000000000000000000000000000000000000000000ffff", - "logIndex": 183, - "blockHash": "0xb425a74b555df57d73ecd58a913856ba672af0d7cc576dac39c4124264e30d7a" + "logIndex": 93, + "blockHash": "0x6b5f1020add0d027b83ccb47f6d467eab22419428e26d10721e1a1c42a771592" } ], - "blockNumber": 18519594, - "cumulativeGasUsed": "12193412", + "blockNumber": 21078154, + "cumulativeGasUsed": "6570070", "status": 1, "byzantium": true }, @@ -1102,7 +1102,7 @@ false ], "numDeployments": 1, - "solcInputHash": "4db3e1d3dd51dbe508dc0a6a04352df6", + "solcInputHash": "dc68422c0ad35a4fe46d461b096b9383", "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"_contractRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"_padding\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"_requiredSignatures\",\"type\":\"uint16\"},{\"internalType\":\"bool\",\"name\":\"_allowForMixedType\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyDeprecated\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArraysDataDoNotMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BlockSubmittedToFastOrDataToOld\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractNotReady\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FCDOverflow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContractType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoChangeToState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotEnoughSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotSupported\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyOwnerOrRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfOrder\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnregisterFirst\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"deprecator\",\"type\":\"address\"}],\"name\":\"LogDeprecation\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"blockId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"staked\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"power\",\"type\":\"uint256\"}],\"name\":\"LogMint\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"executor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"timePadding\",\"type\":\"uint32\"}],\"name\":\"LogPadding\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"blockId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"vote\",\"type\":\"uint256\"}],\"name\":\"LogVoter\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ETH_PREFIX\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_blockId\",\"type\":\"uint256\"}],\"name\":\"blocks\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"dataTimestamp\",\"type\":\"uint32\"}],\"internalType\":\"struct BaseChain.Block\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blocksCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blocksCountOffset\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_offset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_items\",\"type\":\"uint256\"}],\"name\":\"bytesToBytes32Array\",\"outputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"contractRegistry\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deprecate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"fcds\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"dataTimestamp\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockId\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"getBlockIdAtTimestamp\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_blockId\",\"type\":\"uint32\"}],\"name\":\"getBlockRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_blockId\",\"type\":\"uint32\"}],\"name\":\"getBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConsensusData\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"blocksCountOffset\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"sequence\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"lastTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"padding\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"deprecated\",\"type\":\"bool\"}],\"internalType\":\"struct BaseChain.ConsensusData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getCurrentIntValue\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"value\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getCurrentValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_keys\",\"type\":\"bytes32[]\"}],\"name\":\"getCurrentValues\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"uint32[]\",\"name\":\"timestamps\",\"type\":\"uint32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestBlockId\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLeaderAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"getLeaderAddressAtTime\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"getLeaderIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNextLeaderAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStatus\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"timePadding\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"lastDataTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"lastId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"nextLeader\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"nextBlockId\",\"type\":\"uint32\"},{\"internalType\":\"address[]\",\"name\":\"validators\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"powers\",\"type\":\"uint256[]\"},{\"internalType\":\"string[]\",\"name\":\"locations\",\"type\":\"string[]\"},{\"internalType\":\"uint256\",\"name\":\"staked\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"minSignatures\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_key\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_value\",\"type\":\"bytes\"}],\"name\":\"hashLeaf\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isForeign\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastBlockId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_affidavit\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"_v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"_r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_s\",\"type\":\"bytes32\"}],\"name\":\"recoverSigner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"register\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"requiredSignatures\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"roots\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"_padding\",\"type\":\"uint16\"}],\"name\":\"setPadding\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stakingBank\",\"outputs\":[{\"internalType\":\"contract IStakingBank\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stakingBankContract\",\"outputs\":[{\"internalType\":\"contract IStakingBank\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_dataTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"_root\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"_keys\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_values\",\"type\":\"uint256[]\"},{\"internalType\":\"uint8[]\",\"name\":\"_v\",\"type\":\"uint8[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"_r\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"_s\",\"type\":\"bytes32[]\"}],\"name\":\"submit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"tokenContract\",\"outputs\":[{\"internalType\":\"contract ERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_proof\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"_root\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_leaf\",\"type\":\"bytes32\"}],\"name\":\"verifyProof\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_blockId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"_proof\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"_key\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_value\",\"type\":\"bytes\"}],\"name\":\"verifyProofForBlock\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"_blockIds\",\"type\":\"uint32[]\"},{\"internalType\":\"bytes\",\"name\":\"_proofs\",\"type\":\"bytes\"},{\"internalType\":\"uint256[]\",\"name\":\"_proofItemsCounter\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"_leaves\",\"type\":\"bytes32[]\"}],\"name\":\"verifyProofs\",\"outputs\":[{\"internalType\":\"bool[]\",\"name\":\"results\",\"type\":\"bool[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"contract for foreign chains\",\"kind\":\"dev\",\"methods\":{\"blocks(uint256)\":{\"params\":{\"_blockId\":\"ID of submitted block\"},\"returns\":{\"_0\":\"block data (root + timestamp)\"}},\"blocksCount()\":{\"details\":\"number of blocks (consensus rounds) saved in this contract\"},\"bytesToBytes32Array(bytes,uint256,uint256)\":{\"details\":\"this is helper method, that extracts one merkle proof from many hashed provided as bytes\",\"params\":{\"_data\":\"many hashes as bytes\",\"_items\":\"how many hashes to extract\",\"_offset\":\"this is starting point for extraction\"},\"returns\":{\"_0\":\"merkle proof (array of bytes32 hashes)\"}},\"constructor\":{\"params\":{\"_contractRegistry\":\"Registry address\",\"_padding\":\"required \\\"space\\\" between blocks in seconds\",\"_requiredSignatures\":\"number of required signatures for accepting consensus submission\"}},\"getBlockId()\":{\"returns\":{\"_0\":\"current block ID please note, that current ID is not the same as last ID, current means that once padding pass, ID will switch to next one and it will be pointing to empty submit until submit for that ID is done\"}},\"getBlockIdAtTimestamp(uint256)\":{\"details\":\"calculates block ID for provided timestamp this function does not works for past timestamps\",\"params\":{\"_timestamp\":\"current or future timestamp\"},\"returns\":{\"_0\":\"block ID for provided timestamp\"}},\"getBlockRoot(uint32)\":{\"params\":{\"_blockId\":\"consensus ID\"},\"returns\":{\"_0\":\"root for provided consensus ID\"}},\"getBlockTimestamp(uint32)\":{\"params\":{\"_blockId\":\"consensus ID\"},\"returns\":{\"_0\":\"timestamp for provided consensus ID\"}},\"getConsensusData()\":{\"details\":\"getter for `_consensusData`\"},\"getCurrentIntValue(bytes32)\":{\"details\":\"getter for single FCD value in case its type is `int`\",\"params\":{\"_key\":\"FCD key\"},\"returns\":{\"timestamp\":\"FCD timestamp\",\"value\":\"FCD value\"}},\"getCurrentValue(bytes32)\":{\"details\":\"getter for single FCD value\",\"params\":{\"_key\":\"FCD key\"},\"returns\":{\"timestamp\":\"FCD timestamp\",\"value\":\"FCD value\"}},\"getCurrentValues(bytes32[])\":{\"details\":\"batch getter for FCDs\",\"params\":{\"_keys\":\"FCDs keys to fetch\"},\"returns\":{\"timestamps\":\"array of FCDs timestamps\",\"values\":\"array of FCDs values\"}},\"getLatestBlockId()\":{\"returns\":{\"_0\":\"last submitted block ID, please note, that on deployment, when there is no submission for this contract block for last ID will be available in previous contract\"}},\"getLeaderAddress()\":{\"returns\":{\"_0\":\"address of current leader\"}},\"getName()\":{\"returns\":{\"_0\":\"contract name as bytes32\"}},\"getNextLeaderAddress()\":{\"returns\":{\"_0\":\"address of leader for next second\"}},\"getStatus()\":{\"details\":\"helper method that returns all important data about current state of contract\",\"returns\":{\"blockNumber\":\"`block.number`\",\"lastDataTimestamp\":\"timestamp for last submitted consensus\",\"lastId\":\"ID of last submitted consensus\",\"locations\":\"array will be always empty\",\"minSignatures\":\"`this.requiredSignatures`\",\"nextBlockId\":\"block ID for `block.timestamp + padding`\",\"nextLeader\":\"will be always address(0)\",\"powers\":\"array will be always empty\",\"staked\":\"total UMB staked by validators\",\"timePadding\":\"`this.padding`\",\"validators\":\"array will be always empty\"}},\"hashLeaf(bytes,bytes)\":{\"details\":\"creates leaf hash, that has is used in merkle tree\",\"params\":{\"_key\":\"key under which we store the value\",\"_value\":\"value itself as bytes\"},\"returns\":{\"_0\":\"leaf hash\"}},\"isForeign()\":{\"returns\":{\"_0\":\"TRUE if contract is ForeignChain, FALSE otherwise\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"recoverSigner(bytes32,uint8,bytes32,bytes32)\":{\"params\":{\"_affidavit\":\"root and FCDs hashed together\",\"_r\":\"part of signature\",\"_s\":\"part of signature\",\"_v\":\"part of signature\"},\"returns\":{\"_0\":\"signer address\"}},\"register()\":{\"details\":\"this method will be called as a first method in registration process when old contract will be replaced when called, old contract address is still in registry\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setPadding(uint16)\":{\"details\":\"setter for `padding`\"},\"stakingBankContract()\":{\"details\":\"helper method for fetching StakingBank address\"},\"submit(uint32,bytes32,bytes32[],uint256[],uint8[],bytes32[],bytes32[])\":{\"details\":\"method for submitting consensus data\",\"params\":{\"_dataTimestamp\":\"consensus timestamp, this is time for all data in merkle tree including FCDs\",\"_keys\":\"FCDs keys\",\"_r\":\"array of `r` part of validators signatures\",\"_root\":\"merkle root\",\"_s\":\"array of `s` part of validators signatures\",\"_v\":\"array of `v` part of validators signatures\",\"_values\":\"FCDs values\"}},\"tokenContract()\":{\"details\":\"helper method for fetching UMB address\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"unregister()\":{\"details\":\"this method will be called as a last method in registration process when old contract will be replaced when called, new contract address is already in registry\"},\"verifyProof(bytes32[],bytes32,bytes32)\":{\"details\":\"verifies if the leaf is valid leaf for merkle tree\",\"params\":{\"_leaf\":\"leaf hash\",\"_proof\":\"merkle proof for merkle tree\",\"_root\":\"merkle root\"},\"returns\":{\"_0\":\"TRUE if `_leaf` is valid, FALSE otherwise\"}},\"verifyProofForBlock(uint256,bytes32[],bytes,bytes)\":{\"details\":\"verifies, if provided key-value pair was part of consensus\",\"params\":{\"_blockId\":\"consensus ID for which we doing a check\",\"_key\":\"pair key\",\"_proof\":\"merkle proof for pair\",\"_value\":\"pair value\"},\"returns\":{\"_0\":\"TRUE if key-value par was part of consensus, FALSE otherwise\"}},\"verifyProofs(uint32[],bytes,uint256[],bytes32[])\":{\"details\":\"batch method for data verification\",\"params\":{\"_blockIds\":\"consensus IDs for which we doing a checks\",\"_leaves\":\"array of merkle leaves\",\"_proofItemsCounter\":\"array of counters, each counter tells how many hashes proof for each leaf has\",\"_proofs\":\"merkle proofs for all pair, sequence of hashes provided as bytes\"},\"returns\":{\"results\":\"array of verification results, TRUE if leaf is part of consensus, FALSE otherwise\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"deprecate()\":{\"notice\":\"it allows to deprecate contract manually Only new Registry calls `unregister()` where we set deprecated to true In old Registries we don't have this feature, so in order to safely redeploy new Chain we will have to first deprecate current contract manually, then register new contract\"},\"getStatus()\":{\"notice\":\"this method is made to be compatible with MasterChain, but it does not return full data eg validators data will be missing.\"},\"register()\":{\"notice\":\"if this method needs to be called manually (not from Registry) it is important to do it as part of tx batch eg using multisig, we should prepare set of transactions and confirm them all at once\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/ForeignChain.sol\":\"ForeignChain\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":0},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0x24e0364e503a9bbde94c715d26573a76f14cd2a202d45f96f52134ab806b67b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\\n * instead returning `false` on failure. This behavior is nonetheless\\n * conventional and does not conflict with the expectations of ERC20\\n * applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * The default value of {decimals} is 18. To select a different value for\\n * {decimals} you should overload it.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n * overridden;\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\\n * `transferFrom`. This is semantically equivalent to an infinite approval.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * NOTE: Does not update the allowance if the current allowance\\n * is the maximum `uint256`.\\n *\\n * Requirements:\\n *\\n * - `from` and `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) public virtual override returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, amount);\\n _transfer(from, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, allowance(owner, spender) + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n uint256 currentAllowance = allowance(owner, spender);\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n */\\n function _transfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {\\n require(from != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(to != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, amount);\\n\\n uint256 fromBalance = _balances[from];\\n require(fromBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[from] = fromBalance - amount;\\n }\\n _balances[to] += amount;\\n\\n emit Transfer(from, to, amount);\\n\\n _afterTokenTransfer(from, to, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n _balances[account] += amount;\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n }\\n _totalSupply -= amount;\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(\\n address owner,\\n address spender,\\n uint256 amount\\n ) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\\n *\\n * Does not update the allowance amount in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Might emit an {Approval} event.\\n */\\n function _spendAllowance(\\n address owner,\\n address spender,\\n uint256 amount\\n ) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance != type(uint256).max) {\\n require(currentAllowance >= amount, \\\"ERC20: insufficient allowance\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - amount);\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {}\\n}\\n\",\"keccak256\":\"0xe0c8b625a79bac0fe80f17cfb521e072805cc9cef1c96a5caf45b264e74812fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/cryptography/MerkleProof.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev These functions deal with verification of Merkle Trees proofs.\\n *\\n * The proofs can be generated using the JavaScript library\\n * https://github.com/miguelmota/merkletreejs[merkletreejs].\\n * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.\\n *\\n * See `test/utils/cryptography/MerkleProof.test.js` for some examples.\\n *\\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\\n * hashing, or use a hash function other than keccak256 for hashing leaves.\\n * This is because the concatenation of a sorted pair of internal nodes in\\n * the merkle tree could be reinterpreted as a leaf value.\\n */\\nlibrary MerkleProof {\\n /**\\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\\n * defined by `root`. For this, a `proof` must be provided, containing\\n * sibling hashes on the branch from the leaf to the root of the tree. Each\\n * pair of leaves and each pair of pre-images are assumed to be sorted.\\n */\\n function verify(\\n bytes32[] memory proof,\\n bytes32 root,\\n bytes32 leaf\\n ) internal pure returns (bool) {\\n return processProof(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\\n * hash matches the root of the tree. When processing the proof, the pairs\\n * of leafs & pre-images are assumed to be sorted.\\n *\\n * _Available since v4.4._\\n */\\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n bytes32 proofElement = proof[i];\\n if (computedHash <= proofElement) {\\n // Hash(current computed hash + current element of the proof)\\n computedHash = _efficientHash(computedHash, proofElement);\\n } else {\\n // Hash(current element of the proof + current computed hash)\\n computedHash = _efficientHash(proofElement, computedHash);\\n }\\n }\\n return computedHash;\\n }\\n\\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\\n assembly {\\n mstore(0x00, a)\\n mstore(0x20, b)\\n value := keccak256(0x00, 0x40)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaaa504ac17eb0298dcdf5733ce24021b4914f035b97f4400b92827341d3facb3\",\"license\":\"MIT\"},\"@umb-network/toolbox/dist/contracts/lib/ValueDecoder.sol\":{\"content\":\"//SPDX-License-Identifier: Unlicensed\\npragma solidity >=0.6.8;\\n\\nlibrary ValueDecoder {\\n function toUint(bytes memory _bytes) internal pure returns (uint256 value) {\\n assembly {\\n value := mload(add(_bytes, 32))\\n }\\n }\\n\\n function toUint(bytes32 _bytes) internal pure returns (uint256 value) {\\n assembly {\\n value := _bytes\\n }\\n }\\n\\n function toInt(uint224 u) internal pure returns (int256) {\\n int224 i;\\n uint224 max = type(uint224).max;\\n\\n if (u <= (max - 1) / 2) { // positive values\\n assembly {\\n i := add(u, 0)\\n }\\n\\n return i;\\n } else { // negative values\\n assembly {\\n i := sub(sub(u, max), 1)\\n }\\n }\\n\\n return i;\\n }\\n}\\n\\n\",\"keccak256\":\"0x4c27669880111dd724930e6e2cb0baefdb3a8b7b2d6ffc0ec5c5534bc678a852\",\"license\":\"Unlicensed\"},\"contracts/BaseChain.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\\\";\\nimport \\\"@umb-network/toolbox/dist/contracts/lib/ValueDecoder.sol\\\";\\n\\nimport \\\"./interfaces/IBaseChainV1.sol\\\";\\nimport \\\"./interfaces/IStakingBank.sol\\\";\\nimport \\\"./extensions/Registrable.sol\\\";\\nimport \\\"./Registry.sol\\\";\\n\\nabstract contract BaseChain is Registrable, Ownable {\\n using ValueDecoder for bytes;\\n using ValueDecoder for uint224;\\n using MerkleProof for bytes32[];\\n\\n /// @param root merkle root for consensus\\n /// @param dataTimestamp consensus timestamp\\n struct Block {\\n bytes32 root;\\n uint32 dataTimestamp;\\n }\\n\\n /// @param value FCD value\\n /// @param dataTimestamp FCD timestamp\\n struct FirstClassData {\\n uint224 value;\\n uint32 dataTimestamp;\\n }\\n\\n /// @param blocksCountOffset number of all blocks that were generated before switching to this contract\\n /// @param sequence is a total number of blocks (consensus rounds) including previous contracts\\n /// @param lastTimestamp is a timestamp of last submitted block\\n /// @param padding number of seconds that need to pass before new submit will be possible\\n /// @param deprecated flag that changes to TRUE on `unregister`, when TRUE submissions are not longer available\\n struct ConsensusData {\\n uint32 blocksCountOffset;\\n uint32 sequence;\\n uint32 lastTimestamp;\\n uint32 padding;\\n bool deprecated;\\n }\\n\\n uint256 constant public VERSION = 2;\\n\\n bool internal immutable _ALLOW_FOR_MIXED_TYPE; // solhint-disable-line var-name-mixedcase\\n\\n bytes4 constant private _VERSION_SELECTOR = bytes4(keccak256(\\\"VERSION()\\\"));\\n\\n /// @dev minimal number of signatures required for accepting submission (PoA)\\n uint16 internal immutable _REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\\n\\n ConsensusData internal _consensusData;\\n\\n bytes constant public ETH_PREFIX = \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\";\\n\\n /// @dev block id (consensus ID) => root\\n /// consensus ID is at the same time consensus timestamp\\n mapping(uint256 => bytes32) public roots;\\n\\n /// @dev FCD key => FCD data\\n mapping(bytes32 => FirstClassData) public fcds;\\n\\n event LogDeprecation(address indexed deprecator);\\n event LogPadding(address indexed executor, uint32 timePadding);\\n\\n error ArraysDataDoNotMatch();\\n error AlreadyDeprecated();\\n error AlreadyRegistered();\\n error BlockSubmittedToFastOrDataToOld();\\n error ContractNotReady();\\n error FCDOverflow();\\n error InvalidContractType();\\n error NoChangeToState();\\n error OnlyOwnerOrRegistry();\\n error UnregisterFirst();\\n\\n modifier onlyOwnerOrRegistry () {\\n if (msg.sender != address(contractRegistry) && msg.sender != owner()) revert OnlyOwnerOrRegistry();\\n _;\\n }\\n\\n /// @param _contractRegistry Registry address\\n /// @param _padding required \\\"space\\\" between blocks in seconds\\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\\n constructor(\\n IRegistry _contractRegistry,\\n uint32 _padding,\\n uint16 _requiredSignatures,\\n bool _allowForMixedType\\n ) Registrable(_contractRegistry) {\\n _ALLOW_FOR_MIXED_TYPE = _allowForMixedType;\\n _REQUIRED_SIGNATURES = _requiredSignatures;\\n\\n _setPadding(_padding);\\n\\n BaseChain oldChain = BaseChain(_contractRegistry.getAddress(\\\"Chain\\\"));\\n\\n if (address(oldChain) == address(0)) {\\n // if this is first contract in sidechain, then we need to initialise lastTimestamp so submission\\n // can be possible\\n _consensusData.lastTimestamp = uint32(block.timestamp) - _padding - 1;\\n }\\n }\\n\\n /// @dev setter for `padding`\\n function setPadding(uint16 _padding) external {\\n _setPadding(_padding);\\n }\\n\\n /// @notice if this method needs to be called manually (not from Registry)\\n /// it is important to do it as part of tx batch\\n /// eg using multisig, we should prepare set of transactions and confirm them all at once\\n /// @inheritdoc Registrable\\n function register() external override onlyOwnerOrRegistry {\\n address oldChain = contractRegistry.getAddress(\\\"Chain\\\");\\n\\n // registration must be done before address in registry is replaced\\n if (oldChain == address(this)) revert AlreadyRegistered();\\n\\n if (oldChain == address(0x0)) {\\n return;\\n }\\n\\n _cloneLastDataFromPrevChain(oldChain);\\n }\\n\\n /// @inheritdoc Registrable\\n function unregister() external override onlyOwnerOrRegistry {\\n // in case we deprecated contract manually, we simply return\\n if (_consensusData.deprecated) return;\\n\\n address newChain = contractRegistry.getAddress(\\\"Chain\\\");\\n // unregistering must be done after address in registry is replaced\\n if (newChain == address(this)) revert UnregisterFirst();\\n\\n // TODO:\\n // I think we need to remove restriction for type (at least once)\\n // when we will switch to multichain architecture\\n\\n if (!_ALLOW_FOR_MIXED_TYPE) {\\n // can not be replaced with chain of different type\\n if (BaseChain(newChain).isForeign() != this.isForeign()) revert InvalidContractType();\\n }\\n\\n _consensusData.deprecated = true;\\n emit LogDeprecation(msg.sender);\\n }\\n\\n /// @notice it allows to deprecate contract manually\\n /// Only new Registry calls `unregister()` where we set deprecated to true\\n /// In old Registries we don't have this feature, so in order to safely redeploy new Chain\\n /// we will have to first deprecate current contract manually, then register new contract\\n function deprecate() external onlyOwnerOrRegistry {\\n if (_consensusData.deprecated) revert AlreadyDeprecated();\\n\\n _consensusData.deprecated = true;\\n emit LogDeprecation(msg.sender);\\n }\\n\\n /// @dev getter for `_consensusData`\\n function getConsensusData() external view returns (ConsensusData memory) {\\n return _consensusData;\\n }\\n\\n /// @dev number of blocks (consensus rounds) saved in this contract\\n function blocksCount() external view returns (uint256) {\\n return _consensusData.sequence - _consensusData.blocksCountOffset;\\n }\\n\\n function blocksCountOffset() external view returns (uint32) {\\n return _consensusData.blocksCountOffset;\\n }\\n\\n function lastBlockId() external view returns (uint256) {\\n return _consensusData.lastTimestamp;\\n }\\n\\n /// @return TRUE if contract is ForeignChain, FALSE otherwise\\n function isForeign() external pure virtual returns (bool);\\n\\n /// @inheritdoc Registrable\\n function getName() external pure override returns (bytes32) {\\n return \\\"Chain\\\";\\n }\\n\\n /// @param _affidavit root and FCDs hashed together\\n /// @param _v part of signature\\n /// @param _r part of signature\\n /// @param _s part of signature\\n /// @return signer address\\n function recoverSigner(bytes32 _affidavit, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _affidavit));\\n return ecrecover(hash, _v, _r, _s);\\n }\\n\\n /// @param _blockId ID of submitted block\\n /// @return block data (root + timestamp)\\n function blocks(uint256 _blockId) external view returns (Block memory) {\\n return Block(roots[_blockId], uint32(_blockId));\\n }\\n\\n /// @return current block ID\\n /// please note, that current ID is not the same as last ID, current means that once padding pass,\\n /// ID will switch to next one and it will be pointing to empty submit until submit for that ID is done\\n function getBlockId() external view returns (uint32) {\\n if (_consensusData.lastTimestamp == 0) return 0;\\n\\n return getBlockIdAtTimestamp(block.timestamp);\\n }\\n\\n function requiredSignatures() external view returns (uint16) {\\n return _REQUIRED_SIGNATURES;\\n }\\n\\n /// @dev calculates block ID for provided timestamp\\n /// this function does not works for past timestamps\\n /// @param _timestamp current or future timestamp\\n /// @return block ID for provided timestamp\\n function getBlockIdAtTimestamp(uint256 _timestamp) virtual public view returns (uint32) {\\n ConsensusData memory data = _consensusData;\\n\\n unchecked {\\n // we can't overflow because we adding two `uint32`\\n if (data.lastTimestamp + data.padding < _timestamp) {\\n return uint32(_timestamp);\\n }\\n }\\n\\n return data.lastTimestamp;\\n }\\n\\n /// @return last submitted block ID, please note, that on deployment, when there is no submission for this contract\\n /// block for last ID will be available in previous contract\\n function getLatestBlockId() virtual public view returns (uint32) {\\n return _consensusData.lastTimestamp;\\n }\\n\\n /// @dev verifies if the leaf is valid leaf for merkle tree\\n /// @param _proof merkle proof for merkle tree\\n /// @param _root merkle root\\n /// @param _leaf leaf hash\\n /// @return TRUE if `_leaf` is valid, FALSE otherwise\\n function verifyProof(bytes32[] memory _proof, bytes32 _root, bytes32 _leaf) public pure returns (bool) {\\n if (_root == bytes32(0)) {\\n return false;\\n }\\n\\n return _proof.verify(_root, _leaf);\\n }\\n\\n /// @dev creates leaf hash, that has is used in merkle tree\\n /// @param _key key under which we store the value\\n /// @param _value value itself as bytes\\n /// @return leaf hash\\n function hashLeaf(bytes memory _key, bytes memory _value) public pure returns (bytes32) {\\n return keccak256(abi.encodePacked(_key, _value));\\n }\\n\\n /// @dev verifies, if provided key-value pair was part of consensus\\n /// @param _blockId consensus ID for which we doing a check\\n /// @param _proof merkle proof for pair\\n /// @param _key pair key\\n /// @param _value pair value\\n /// @return TRUE if key-value par was part of consensus, FALSE otherwise\\n function verifyProofForBlock(\\n uint256 _blockId,\\n bytes32[] memory _proof,\\n bytes memory _key,\\n bytes memory _value\\n )\\n public\\n view\\n returns (bool)\\n {\\n return _proof.verify(roots[_blockId], keccak256(abi.encodePacked(_key, _value)));\\n }\\n\\n /// @dev this is helper method, that extracts one merkle proof from many hashed provided as bytes\\n /// @param _data many hashes as bytes\\n /// @param _offset this is starting point for extraction\\n /// @param _items how many hashes to extract\\n /// @return merkle proof (array of bytes32 hashes)\\n function bytesToBytes32Array(\\n bytes memory _data,\\n uint256 _offset,\\n uint256 _items\\n )\\n public\\n pure\\n returns (bytes32[] memory)\\n {\\n bytes32[] memory dataList = new bytes32[](_items);\\n\\n // we can unchecked because we working only with `i` and `_offset`\\n // in case of wrong `_offset` it will throw\\n unchecked {\\n for (uint256 i = 0; i < _items; i++) {\\n bytes32 temp;\\n uint256 idx = (i + 1 + _offset) * 32;\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n temp := mload(add(_data, idx))\\n }\\n\\n dataList[i] = temp;\\n }\\n }\\n\\n return (dataList);\\n }\\n\\n /// @dev batch method for data verification\\n /// @param _blockIds consensus IDs for which we doing a checks\\n /// @param _proofs merkle proofs for all pair, sequence of hashes provided as bytes\\n /// @param _proofItemsCounter array of counters, each counter tells how many hashes proof for each leaf has\\n /// @param _leaves array of merkle leaves\\n /// @return results array of verification results, TRUE if leaf is part of consensus, FALSE otherwise\\n function verifyProofs(\\n uint32[] memory _blockIds,\\n bytes memory _proofs,\\n uint256[] memory _proofItemsCounter,\\n bytes32[] memory _leaves\\n )\\n public\\n view\\n returns (bool[] memory results)\\n {\\n results = new bool[](_leaves.length);\\n uint256 offset = 0;\\n\\n for (uint256 i = 0; i < _leaves.length;) {\\n results[i] = bytesToBytes32Array(_proofs, offset, _proofItemsCounter[i]).verify(\\n roots[_blockIds[i]], _leaves[i]\\n );\\n\\n unchecked {\\n // we can uncheck because it will not overflow in a lifetime, and if someone provide invalid counter\\n // we verification will not be valid (or we throw because of invalid memory access)\\n offset += _proofItemsCounter[i];\\n // we can uncheck because `i` will not overflow in a lifetime\\n i++;\\n }\\n }\\n }\\n\\n /// @param _blockId consensus ID\\n /// @return root for provided consensus ID\\n function getBlockRoot(uint32 _blockId) external view returns (bytes32) {\\n return roots[_blockId];\\n }\\n\\n /// @param _blockId consensus ID\\n /// @return timestamp for provided consensus ID\\n function getBlockTimestamp(uint32 _blockId) external view returns (uint32) {\\n return roots[_blockId] == bytes32(0) ? 0 : _blockId;\\n }\\n\\n /// @dev batch getter for FCDs\\n /// @param _keys FCDs keys to fetch\\n /// @return values array of FCDs values\\n /// @return timestamps array of FCDs timestamps\\n function getCurrentValues(bytes32[] calldata _keys)\\n external\\n view\\n returns (uint256[] memory values, uint32[] memory timestamps)\\n {\\n timestamps = new uint32[](_keys.length);\\n values = new uint256[](_keys.length);\\n\\n for (uint i=0; i<_keys.length;) {\\n FirstClassData storage numericFCD = fcds[_keys[i]];\\n values[i] = uint256(numericFCD.value);\\n timestamps[i] = numericFCD.dataTimestamp;\\n\\n unchecked {\\n // we can uncheck because `i` will not overflow in a lifetime\\n i++;\\n }\\n }\\n }\\n\\n /// @dev getter for single FCD value\\n /// @param _key FCD key\\n /// @return value FCD value\\n /// @return timestamp FCD timestamp\\n function getCurrentValue(bytes32 _key) external view returns (uint256 value, uint256 timestamp) {\\n FirstClassData storage numericFCD = fcds[_key];\\n return (uint256(numericFCD.value), numericFCD.dataTimestamp);\\n }\\n\\n /// @dev getter for single FCD value in case its type is `int`\\n /// @param _key FCD key\\n /// @return value FCD value\\n /// @return timestamp FCD timestamp\\n function getCurrentIntValue(bytes32 _key) external view returns (int256 value, uint256 timestamp) {\\n FirstClassData storage numericFCD = fcds[_key];\\n return (numericFCD.value.toInt(), numericFCD.dataTimestamp);\\n }\\n\\n function _setPadding(uint32 _padding) internal onlyOwner {\\n if (_consensusData.padding == _padding) revert NoChangeToState();\\n\\n _consensusData.padding = _padding;\\n emit LogPadding(msg.sender, _padding);\\n }\\n\\n /// @dev we cloning last block time, because we will need reference point for next submissions\\n function _cloneLastDataFromPrevChain(address _prevChain) internal {\\n (bool success, bytes memory v) = _prevChain.staticcall(abi.encode(_VERSION_SELECTOR));\\n uint256 prevVersion = success ? abi.decode(v, (uint256)) : 1;\\n\\n if (prevVersion == 1) {\\n uint32 latestId = IBaseChainV1(address(_prevChain)).getLatestBlockId();\\n _consensusData.lastTimestamp = IBaseChainV1(address(_prevChain)).getBlockTimestamp(latestId);\\n\\n // +1 because getLatestBlockId subtracts 1\\n // +1 because it might be situation when tx is already in progress in old contract\\n // and old contract do not have deprecated flag\\n _consensusData.sequence = latestId + 2;\\n _consensusData.blocksCountOffset = latestId + 2;\\n } else { // VERSION 2\\n // with new Registry, we have register/unregister methods\\n // Chain will be deprecated, so there is no need to do \\\"+1\\\" as in old version\\n // TODO what with current Registries??\\n // we need a way to make it deprecated!\\n ConsensusData memory data = BaseChain(_prevChain).getConsensusData();\\n\\n _consensusData.sequence = data.sequence;\\n _consensusData.blocksCountOffset = data.sequence;\\n _consensusData.lastTimestamp = data.lastTimestamp;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcc7d655ad64f0a17cd71331260cf48828f0396e5e3b1428b6690c12f35a95db7\",\"license\":\"MIT\"},\"contracts/Chain.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./BaseChain.sol\\\";\\n\\ncontract Chain is BaseChain {\\n IStakingBank public immutable stakingBank;\\n\\n event LogMint(address indexed minter, uint256 blockId, uint256 staked, uint256 power);\\n event LogVoter(uint256 indexed blockId, address indexed voter, uint256 vote);\\n\\n error NotEnoughSignatures();\\n error SignaturesOutOfOrder();\\n\\n /// @param _contractRegistry Registry address\\n /// @param _padding required \\\"space\\\" between blocks in seconds\\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\\n /// @param _allowForMixedType we have two \\\"types\\\" of Chain: HomeChain and ForeignChain, when we redeploying\\n /// we don't want to mix up them, so we checking, if new Chain has the same type as current one.\\n /// However, when we will be switching from one homechain to another one, we have to allow for this mixing up.\\n /// This flag will tell contract, if this is the case.\\n constructor(\\n IRegistry _contractRegistry,\\n uint32 _padding,\\n uint16 _requiredSignatures,\\n bool _allowForMixedType\\n ) BaseChain(_contractRegistry, _padding, _requiredSignatures, _allowForMixedType) {\\n stakingBank = IStakingBank(_contractRegistry.requireAndGetAddress(\\\"StakingBank\\\"));\\n }\\n\\n /// @dev method for submitting consensus data\\n /// @param _dataTimestamp consensus timestamp, this is time for all data in merkle tree including FCDs\\n /// @param _root merkle root\\n /// @param _keys FCDs keys\\n /// @param _values FCDs values\\n /// @param _v array of `v` part of validators signatures\\n /// @param _r array of `r` part of validators signatures\\n /// @param _s array of `s` part of validators signatures\\n // solhint-disable-next-line function-max-lines, code-complexity\\n function submit(\\n uint32 _dataTimestamp,\\n bytes32 _root,\\n bytes32[] memory _keys,\\n uint256[] memory _values,\\n uint8[] memory _v,\\n bytes32[] memory _r,\\n bytes32[] memory _s\\n ) external {\\n // below two checks are only for pretty errors, so we can safe gas and allow for raw revert\\n // if (_keys.length != _values.length) revert ArraysDataDoNotMatch();\\n // if (_v.length != _r.length || _r.length != _s.length) revert ArraysDataDoNotMatch();\\n\\n _verifySubmitTimestampAndIncSequence(_dataTimestamp);\\n\\n // we can't expect minter will have exactly the same timestamp\\n // but for sure we can demand not to be off by a lot, that's why +3sec\\n // temporary remove this condition, because recently on ropsten we see cases when minter/node\\n // can be even 100sec behind\\n // require(_dataTimestamp <= block.timestamp + 3,\\n // string(abi.encodePacked(\\\"oh, so you can predict the future:\\\", _dataTimestamp - block.timestamp + 48)));\\n\\n bytes memory testimony = abi.encodePacked(_dataTimestamp, _root);\\n\\n for (uint256 i = 0; i < _keys.length;) {\\n if (uint224(_values[i]) != _values[i]) revert FCDOverflow();\\n\\n fcds[_keys[i]] = FirstClassData(uint224(_values[i]), _dataTimestamp);\\n testimony = abi.encodePacked(testimony, _keys[i], _values[i]);\\n\\n unchecked {\\n // we can't pass enough data to overflow\\n i++;\\n }\\n }\\n\\n uint256 signatures = 0;\\n uint256 power = 0;\\n //uint256 staked = stakingBank.totalSupply();\\n bytes32 affidavit = keccak256(testimony);\\n\\n address prevSigner = address(0x0);\\n\\n for (uint256 i; i < _v.length;) {\\n address signer = recoverSigner(affidavit, _v[i], _r[i], _s[i]);\\n uint256 balance = stakingBank.balanceOf(signer);\\n\\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\\n\\n prevSigner = signer;\\n\\n if (balance == 0) {\\n unchecked { i++; }\\n continue;\\n }\\n\\n signatures++;\\n emit LogVoter(uint256(_dataTimestamp), signer, balance);\\n\\n unchecked {\\n // we can't overflow because that means token overflowed\\n // and even if we do, we will get lower power\\n power += balance;\\n i++;\\n }\\n }\\n\\n if (signatures < _REQUIRED_SIGNATURES) revert NotEnoughSignatures();\\n\\n emit LogMint(msg.sender, _dataTimestamp, stakingBank.totalSupply(), power);\\n\\n // TODO remember to protect against flash loans when DPoS will be in place\\n // we turn on power once we have DPoS in action, we have PoA now\\n // require(power * 100 / staked >= 66, \\\"not enough power was gathered\\\");\\n\\n roots[_dataTimestamp] = _root;\\n _consensusData.lastTimestamp = _dataTimestamp;\\n }\\n\\n /// @inheritdoc BaseChain\\n function isForeign() external pure virtual override returns (bool) {\\n return false;\\n }\\n\\n /// @dev helper method that returns all important data about current state of contract\\n /// @return blockNumber `block.number`\\n /// @return timePadding `this.padding`\\n /// @return lastDataTimestamp timestamp for last submitted consensus\\n /// @return lastId ID of last submitted consensus\\n /// @return nextLeader leader for `block.timestamp + 1`\\n /// @return nextBlockId block ID for `block.timestamp + padding`\\n /// @return validators array of all validators addresses\\n /// @return powers array of all validators powers\\n /// @return locations array of all validators locations\\n /// @return staked total UMB staked by validators\\n /// @return minSignatures `this.requiredSignatures`\\n function getStatus() external view virtual returns(\\n uint256 blockNumber,\\n uint32 timePadding,\\n uint32 lastDataTimestamp,\\n uint32 lastId,\\n address nextLeader,\\n uint32 nextBlockId,\\n address[] memory validators,\\n uint256[] memory powers,\\n string[] memory locations,\\n uint256 staked,\\n uint16 minSignatures\\n ) {\\n ConsensusData memory data = _consensusData;\\n\\n blockNumber = block.number;\\n timePadding = data.padding;\\n lastId = data.lastTimestamp;\\n lastDataTimestamp = lastId;\\n minSignatures = _REQUIRED_SIGNATURES;\\n\\n staked = stakingBank.totalSupply();\\n uint256 numberOfValidators = stakingBank.getNumberOfValidators();\\n powers = new uint256[](numberOfValidators);\\n validators = new address[](numberOfValidators);\\n locations = new string[](numberOfValidators);\\n\\n for (uint256 i = 0; i < numberOfValidators;) {\\n validators[i] = stakingBank.addresses(i);\\n (, locations[i]) = stakingBank.validators(validators[i]);\\n powers[i] = stakingBank.balanceOf(validators[i]);\\n\\n unchecked {\\n // we will run out of gas before overflow happen\\n i++;\\n }\\n }\\n\\n unchecked {\\n // we will not overflow with timestamp in a lifetime\\n nextBlockId = lastId + data.padding + 1;\\n\\n nextLeader = numberOfValidators > 0\\n // we will not overflow with timestamp in a lifetime\\n ? validators[getLeaderIndex(numberOfValidators, block.timestamp + 1)]\\n : address(0);\\n }\\n }\\n\\n /// @return address of leader for next second\\n function getNextLeaderAddress() external view returns (address) {\\n return getLeaderAddressAtTime(block.timestamp + 1);\\n }\\n\\n /// @return address of current leader\\n function getLeaderAddress() external view returns (address) {\\n return getLeaderAddressAtTime(block.timestamp);\\n }\\n\\n /// @param _numberOfValidators total number of validators\\n /// @param _timestamp timestamp for which you want to calculate index\\n /// @return leader index, use it for StakingBank.addresses[index] to fetch leader address\\n function getLeaderIndex(uint256 _numberOfValidators, uint256 _timestamp) public view virtual returns (uint256) {\\n ConsensusData memory data = _consensusData;\\n\\n unchecked {\\n // we will not overflow on `timestamp` and `padding` in a life time\\n // timePadding + 1 => because padding is a space between blocks,\\n // so next round starts on first block after padding\\n // TODO will it work for off-chain??\\n uint256 validatorIndex = data.sequence + (_timestamp - data.lastTimestamp) / (data.padding + 1);\\n\\n return validatorIndex % _numberOfValidators;\\n }\\n }\\n\\n // @todo - properly handled non-enabled validators, newly added validators, and validators with low stake\\n /// @param _timestamp timestamp for which you want to calculate leader address\\n /// @return leader address for provider timestamp\\n function getLeaderAddressAtTime(uint256 _timestamp) public view virtual returns (address) {\\n uint256 numberOfValidators = stakingBank.getNumberOfValidators();\\n\\n if (numberOfValidators == 0) {\\n return address(0x0);\\n }\\n\\n uint256 validatorIndex = getLeaderIndex(numberOfValidators, _timestamp);\\n\\n return stakingBank.addresses(validatorIndex);\\n }\\n\\n /// @dev we had stack too deep in `submit` so this method was created as a solution\\n // we increasing `_consensusData.sequence` here so we don't have to read sequence again in other place\\n function _verifySubmitTimestampAndIncSequence(uint256 _dataTimestamp) internal {\\n ConsensusData memory data = _consensusData;\\n\\n // `data.lastTimestamp` must be setup either on deployment\\n // or via cloning from previous contract\\n if (data.lastTimestamp == 0) revert ContractNotReady();\\n\\n unchecked {\\n // we will not overflow with timestamp and padding in a life time\\n if (data.lastTimestamp + data.padding >= _dataTimestamp) revert BlockSubmittedToFastOrDataToOld();\\n }\\n\\n unchecked {\\n // we will not overflow in a life time\\n _consensusData.sequence = uint32(data.sequence + 1);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9eb872eaabac21d63c759e91507992710232a362afad6aa3221a8758d66f4e69\",\"license\":\"MIT\"},\"contracts/ForeignChain.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./Chain.sol\\\";\\n\\n/// @dev contract for foreign chains\\ncontract ForeignChain is Chain {\\n error NotSupported();\\n\\n /// @param _contractRegistry Registry address\\n /// @param _padding required \\\"space\\\" between blocks in seconds\\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\\n constructor(\\n IRegistry _contractRegistry,\\n uint32 _padding,\\n uint16 _requiredSignatures,\\n bool _allowForMixedType\\n ) Chain(_contractRegistry, _padding, _requiredSignatures, _allowForMixedType) {\\n // no additional configuration needed\\n }\\n\\n /// @inheritdoc BaseChain\\n function isForeign() external pure override returns (bool) {\\n return true;\\n }\\n\\n /// @inheritdoc Chain\\n /// @notice this method is made to be compatible with MasterChain, but it does not return full data eg validators\\n /// data will be missing.\\n /// @return blockNumber `block.number`\\n /// @return timePadding `this.padding`\\n /// @return lastDataTimestamp timestamp for last submitted consensus\\n /// @return lastId ID of last submitted consensus\\n /// @return nextLeader will be always address(0)\\n /// @return nextBlockId block ID for `block.timestamp + padding`\\n /// @return validators array will be always empty\\n /// @return powers array will be always empty\\n /// @return locations array will be always empty\\n /// @return staked total UMB staked by validators\\n /// @return minSignatures `this.requiredSignatures`\\n function getStatus() external view override returns(\\n uint256 blockNumber,\\n uint32 timePadding,\\n uint32 lastDataTimestamp,\\n uint32 lastId,\\n address nextLeader,\\n uint32 nextBlockId,\\n address[] memory validators,\\n uint256[] memory powers,\\n string[] memory locations,\\n uint256 staked,\\n uint16 minSignatures\\n ) {\\n ConsensusData memory data = _consensusData;\\n\\n blockNumber = block.number;\\n timePadding = data.padding;\\n lastId = data.lastTimestamp;\\n lastDataTimestamp = lastId;\\n minSignatures = _REQUIRED_SIGNATURES;\\n\\n staked = stakingBank.totalSupply();\\n uint256 numberOfValidators = 0;\\n powers = new uint256[](numberOfValidators);\\n validators = new address[](numberOfValidators);\\n locations = new string[](numberOfValidators);\\n nextLeader = address(0);\\n\\n unchecked {\\n // we will not overflow with timestamp in a lifetime\\n nextBlockId = lastId + data.padding + 1;\\n }\\n }\\n\\n function getLeaderIndex(uint256, uint256) public pure override returns (uint256) {\\n revert NotSupported();\\n }\\n\\n function getLeaderAddressAtTime(uint256) public pure override returns (address) {\\n revert NotSupported();\\n }\\n}\\n\",\"keccak256\":\"0x5b895277453aa3741c2659f335c2a4d587ff231615e4ee160bd2ec8e78778d49\",\"license\":\"MIT\"},\"contracts/Registry.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\n// Inheritance\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport \\\"./extensions/Registrable.sol\\\";\\nimport \\\"./interfaces/IRegistry.sol\\\";\\n\\n/// @dev contracts registry\\n/// protocol uses this registry to fetch current contract addresses\\ncontract Registry is IRegistry, Ownable {\\n /// name => contract address\\n mapping(bytes32 => address) public registry;\\n\\n\\n error NameNotRegistered();\\n error ArraysDataDoNotMatch();\\n\\n /// @inheritdoc IRegistry\\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external onlyOwner {\\n if (_names.length != _destinations.length) revert ArraysDataDoNotMatch();\\n\\n for (uint i = 0; i < _names.length;) {\\n registry[_names[i]] = _destinations[i];\\n emit LogRegistered(_destinations[i], _names[i]);\\n\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @inheritdoc IRegistry\\n function importContracts(address[] calldata _destinations) external onlyOwner {\\n for (uint i = 0; i < _destinations.length;) {\\n bytes32 name = Registrable(_destinations[i]).getName();\\n registry[name] = _destinations[i];\\n emit LogRegistered(_destinations[i], name);\\n\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @inheritdoc IRegistry\\n function atomicUpdate(address _newContract) external onlyOwner {\\n Registrable(_newContract).register();\\n\\n bytes32 name = Registrable(_newContract).getName();\\n address oldContract = registry[name];\\n registry[name] = _newContract;\\n\\n Registrable(oldContract).unregister();\\n\\n emit LogRegistered(_newContract, name);\\n }\\n\\n /// @inheritdoc IRegistry\\n function requireAndGetAddress(bytes32 name) external view returns (address) {\\n address _foundAddress = registry[name];\\n if (_foundAddress == address(0)) revert NameNotRegistered();\\n\\n return _foundAddress;\\n }\\n\\n /// @inheritdoc IRegistry\\n function getAddress(bytes32 _bytes) external view returns (address) {\\n return registry[_bytes];\\n }\\n\\n /// @inheritdoc IRegistry\\n function getAddressByString(string memory _name) public view returns (address) {\\n return registry[stringToBytes32(_name)];\\n }\\n\\n /// @inheritdoc IRegistry\\n function stringToBytes32(string memory _string) public pure returns (bytes32 result) {\\n bytes memory tempEmptyStringTest = bytes(_string);\\n\\n if (tempEmptyStringTest.length == 0) {\\n return 0x0;\\n }\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n result := mload(add(_string, 32))\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcf8ac18bf5766420afcc70f34339192fa67169106ccdb51573267a1ffd95fb81\",\"license\":\"MIT\"},\"contracts/extensions/Registrable.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"../interfaces/IRegistry.sol\\\";\\nimport \\\"../interfaces/IStakingBank.sol\\\";\\n\\n/// @dev Any contract that we want to register in ContractRegistry, must inherit from Registrable\\nabstract contract Registrable {\\n IRegistry public immutable contractRegistry;\\n\\n modifier onlyFromContract(address _msgSender, bytes32 _contractName) {\\n require(\\n contractRegistry.getAddress(_contractName) == _msgSender,\\n string(abi.encodePacked(\\\"caller is not \\\", _contractName))\\n );\\n _;\\n }\\n\\n modifier withRegistrySetUp() {\\n require(address(contractRegistry) != address(0x0), \\\"_registry is empty\\\");\\n _;\\n }\\n\\n constructor(IRegistry _contractRegistry) {\\n require(address(_contractRegistry) != address(0x0), \\\"_registry is empty\\\");\\n contractRegistry = _contractRegistry;\\n }\\n\\n /// @dev this method will be called as a first method in registration process when old contract will be replaced\\n /// when called, old contract address is still in registry\\n function register() virtual external;\\n\\n /// @dev this method will be called as a last method in registration process when old contract will be replaced\\n /// when called, new contract address is already in registry\\n function unregister() virtual external;\\n\\n /// @return contract name as bytes32\\n function getName() virtual external pure returns (bytes32);\\n\\n /// @dev helper method for fetching StakingBank address\\n function stakingBankContract() public view returns (IStakingBank) {\\n return IStakingBank(contractRegistry.requireAndGetAddress(\\\"StakingBank\\\"));\\n }\\n\\n /// @dev helper method for fetching UMB address\\n function tokenContract() public view withRegistrySetUp returns (ERC20) {\\n return ERC20(contractRegistry.requireAndGetAddress(\\\"UMB\\\"));\\n }\\n}\\n\",\"keccak256\":\"0x58413fc819ff8f78ba80a9339bf6b4bb818932ddef0ce58dd4813acba01bda8c\",\"license\":\"MIT\"},\"contracts/interfaces/IBaseChainV1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IBaseChainV1 {\\n /// @dev number of blocks (consensus rounds) saved in this contract\\n function blocksCount() external returns (uint32);\\n\\n /// @dev number of all blocks that were generated before switching to this contract\\n /// please note, that there might be a gap of one block when we switching from old to new contract\\n /// see constructor for details\\n function blocksCountOffset() external returns (uint32);\\n\\n function getLatestBlockId() external view returns (uint32);\\n\\n function getBlockTimestamp(uint32 _blockId) external view returns (uint32);\\n\\n function getStatus() external view returns (\\n uint256 blockNumber,\\n uint16 timePadding,\\n uint32 lastDataTimestamp,\\n uint32 lastId,\\n uint32 nextBlockId\\n );\\n}\\n\",\"keccak256\":\"0x4196faa25b921cae447328983f172ee4289591b4136fdde54ad05552c559d371\",\"license\":\"MIT\"},\"contracts/interfaces/IRegistry.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\n\\ninterface IRegistry {\\n event LogRegistered(address indexed destination, bytes32 name);\\n\\n /// @dev imports new contract addresses and override old addresses, if they exist under provided name\\n /// This method can be used for contracts that for some reason do not have `getName` method\\n /// @param _names array of contract names that we want to register\\n /// @param _destinations array of contract addresses\\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external;\\n\\n /// @dev imports new contracts and override old addresses, if they exist.\\n /// Names of contracts are fetched directly from each contract by calling `getName`\\n /// @param _destinations array of contract addresses\\n function importContracts(address[] calldata _destinations) external;\\n\\n /// @dev this method ensure, that old and new contract is aware of it state in registry\\n /// Note: BSC registry does not have this method. This method was introduced in later stage.\\n /// @param _newContract address of contract that will replace old one\\n function atomicUpdate(address _newContract) external;\\n\\n /// @dev similar to `getAddress` but throws when contract name not exists\\n /// @param name contract name\\n /// @return contract address registered under provided name or throws, if does not exists\\n function requireAndGetAddress(bytes32 name) external view returns (address);\\n\\n /// @param name contract name in a form of bytes32\\n /// @return contract address registered under provided name\\n function getAddress(bytes32 name) external view returns (address);\\n\\n /// @param _name contract name\\n /// @return contract address assigned to the name or address(0) if not exists\\n function getAddressByString(string memory _name) external view returns (address);\\n\\n /// @dev helper method that converts string to bytes32,\\n /// you can use to to generate contract name\\n function stringToBytes32(string memory _string) external pure returns (bytes32 result);\\n}\\n\",\"keccak256\":\"0xa0099ecf4182138fda7a0733407784461410c245de67c1e7ba7cd7c9595e054f\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBank.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IStakingBank is IERC20 {\\n /// @param id address of validator wallet\\n /// @param location URL of the validator API\\n struct Validator {\\n address id;\\n string location;\\n }\\n\\n event LogValidatorRegistered(address indexed id);\\n event LogValidatorUpdated(address indexed id);\\n event LogValidatorRemoved(address indexed id);\\n event LogMinAmountForStake(uint256 minAmountForStake);\\n\\n /// @dev setter for `minAmountForStake`\\n function setMinAmountForStake(uint256 _minAmountForStake) external;\\n\\n /// @dev allows to stake `token` by validators\\n /// Validator needs to approve StakingBank beforehand\\n /// @param _value amount of tokens to stake\\n function stake(uint256 _value) external;\\n\\n /// @dev notification about approval from `_from` address on UMB token\\n /// Staking bank will stake max approved amount from `_from` address\\n /// @param _from address which approved token spend for IStakingBank\\n function receiveApproval(address _from) external returns (bool success);\\n\\n /// @dev withdraws stake tokens\\n /// it throws, when balance will be less than required minimum for stake\\n /// to withdraw all use `exit`\\n function withdraw(uint256 _value) external returns (bool success);\\n\\n /// @dev unstake and withdraw all tokens\\n function exit() external returns (bool success);\\n\\n /// @dev creates (register) new validator\\n /// @param _id validator address\\n /// @param _location location URL of the validator API\\n function create(address _id, string calldata _location) external;\\n\\n /// @dev removes validator\\n /// @param _id validator wallet\\n function remove(address _id) external;\\n\\n /// @dev updates validator location\\n /// @param _id validator wallet\\n /// @param _location new validator URL\\n function update(address _id, string calldata _location) external;\\n\\n /// @return total number of registered validators (with and without balance)\\n function getNumberOfValidators() external view returns (uint256);\\n\\n /// @dev gets validator address for provided index\\n /// @param _ix index in array of list of all validators wallets\\n function addresses(uint256 _ix) external view returns (address);\\n\\n /// @param _id address of validator\\n /// @return id address of validator\\n /// @return location URL of validator\\n function validators(address _id) external view returns (address id, string memory location);\\n}\\n\",\"keccak256\":\"0x2c518aeab8b0b3a364fafaec559d3ff0dc6a119f8d203fa31ef7ad667ca0f7b9\",\"license\":\"MIT\"}},\"version\":1}", "bytecode": "0x6101006040523480156200001257600080fd5b50604051620057fa380380620057fa83398181016040528101906200003891906200067f565b838383838383838383600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603620000b3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620000aa9062000752565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250505062000108620000fc620002ee60201b60201c565b620002f660201b60201c565b80151560a0811515815250508161ffff1660c08161ffff16815250506200013583620003ba60201b60201c565b60008473ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b815260040162000170906200079a565b602060405180830381865afa1580156200018e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001b49190620007e6565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036200022b5760018442620001fb919062000847565b62000207919062000847565b600160000160086101000a81548163ffffffff021916908363ffffffff1602179055505b50505050508373ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b81526004016200026990620008a8565b602060405180830381865afa15801562000287573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002ad9190620007e6565b73ffffffffffffffffffffffffffffffffffffffff1660e08173ffffffffffffffffffffffffffffffffffffffff1681525050505050505050505062000963565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b620003ca620002ee60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16620003f06200051b60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff161462000449576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620004409062000913565b60405180910390fd5b8063ffffffff166001600001600c9054906101000a900463ffffffff1663ffffffff1603620004a4576040517f96f56f6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600001600c6101000a81548163ffffffff021916908363ffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167f02ff77a0f68d11f7efb906f331b2dda82916de8ba9c37dda2a95817936a530ec8260405162000510919062000946565b60405180910390a250565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620005768262000549565b9050919050565b60006200058a8262000569565b9050919050565b6200059c816200057d565b8114620005a857600080fd5b50565b600081519050620005bc8162000591565b92915050565b600063ffffffff82169050919050565b620005dd81620005c2565b8114620005e957600080fd5b50565b600081519050620005fd81620005d2565b92915050565b600061ffff82169050919050565b6200061c8162000603565b81146200062857600080fd5b50565b6000815190506200063c8162000611565b92915050565b60008115159050919050565b620006598162000642565b81146200066557600080fd5b50565b60008151905062000679816200064e565b92915050565b600080600080608085870312156200069c576200069b62000544565b5b6000620006ac87828801620005ab565b9450506020620006bf87828801620005ec565b9350506040620006d2878288016200062b565b9250506060620006e58782880162000668565b91505092959194509250565b600082825260208201905092915050565b7f5f726567697374727920697320656d7074790000000000000000000000000000600082015250565b60006200073a601283620006f1565b9150620007478262000702565b602082019050919050565b600060208201905081810360008301526200076d816200072b565b9050919050565b7f436861696e000000000000000000000000000000000000000000000000000000815250565b6000602082019050620007b06000830162000774565b919050565b620007c08162000569565b8114620007cc57600080fd5b50565b600081519050620007e081620007b5565b92915050565b600060208284031215620007ff57620007fe62000544565b5b60006200080f84828501620007cf565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006200085482620005c2565b91506200086183620005c2565b92508282101562000877576200087662000818565b5b828203905092915050565b7f5374616b696e6742616e6b000000000000000000000000000000000000000000815250565b6000602082019050620008be6000830162000882565b919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000620008fb602083620006f1565b91506200090882620008c3565b602082019050919050565b600060208201905081810360008301526200092e81620008ec565b9050919050565b6200094081620005c2565b82525050565b60006020820190506200095d600083018462000935565b92915050565b60805160a05160c05160e051614e02620009f860003960008181610eac015281816112260152818161145101526116880152600081816113ba015281816116650152611bd30152600061230f01526000818161082701528181610a1d01528181610ae501528181611839015281816118b00152818161194f01528181611d0b0152818161213101526122100152614e026000f3fe608060405234801561001057600080fd5b50600436106101f95760003560e01c80630f2acc3e146101fe5780630fcc0c281461022e57806317d7de7c14610238578063199dadc5146102565780631aa3a00814610286578063243b68f91461029057806324c89a49146102c057806326f3ab8b146102de57806334ba34811461030f5780633bb8819d1461032d57806340a9e5e31461035e578063485e055d1461037a5780634bc935d7146103965780634e69d560146103c657806355a373d6146103ee578063637180a81461040c5780636d046c3e1461042a578063715018a6146104485780637353cbcb1461045257806377839fe614610470578063805d34321461048e5780638d068043146104be5780638da5cb5b146104dc5780639f6119d7146104fa578063a0bc937414610518578063abf410e514610536578063adf1639d14610554578063bef9f8a114610585578063bf66e3ba146105b5578063c2a4250b146105e5578063c2b40ae414610603578063c3369db814610633578063ca4d29d214610663578063cbb1b2c714610693578063d3d3ea08146106c4578063d45167d0146106e2578063e76c0b5714610712578063e79a198f14610730578063ed9975c31461073a578063ef19f3e714610758578063f25b3f9914610788578063f2fde38b146107b8578063ffa1ad74146107d4575b600080fd5b61021860048036038101906102139190613017565b6107f2565b60405161022591906130a8565b60405180910390f35b610236610825565b005b610240610997565b60405161024d91906130a8565b60405180910390f35b610270600480360381019061026b91906131ed565b6109bf565b60405161027d91906132c3565b60405180910390f35b61028e610a1b565b005b6102aa60048036038101906102a591906132de565b610c29565b6040516102b7919061340b565b60405180910390f35b6102c8610cd2565b6040516102d591906134b5565b60405180910390f35b6102f860048036038101906102f39190613532565b610d0b565b60405161030692919061370b565b60405180910390f35b610317610eaa565b60405161032491906137c1565b60405180910390f35b610347600480360381019061034291906137dc565b610ece565b604051610355929190613831565b60405180910390f35b61037860048036038101906103739190613894565b610f63565b005b610394600480360381019061038f9190613aac565b610f73565b005b6103b060048036038101906103ab9190613bda565b611546565b6040516103bd91906132c3565b60405180910390f35b6103ce61157a565b6040516103e59b9a99989796959493929190613e5d565b60405180910390f35b6103f661181e565b6040516104039190613f3e565b60405180910390f35b61041461194b565b60405161042191906137c1565b60405180910390f35b6104326119ea565b60405161043f91906132c3565b60405180910390f35b6104506119f3565b005b61045a611a7b565b6040516104679190613f59565b60405180910390f35b610478611abe565b6040516104859190613f74565b60405180910390f35b6104a860048036038101906104a39190613f8f565b611adb565b6040516104b59190613f74565b60405180910390f35b6104c6611bcf565b6040516104d39190613fbc565b60405180910390f35b6104e4611bf7565b6040516104f19190613fd7565b60405180910390f35b610502611c20565b60405161050f9190613fd7565b60405180910390f35b610520611c3c565b60405161052d9190614069565b60405180910390f35b61053e611d09565b60405161054b91906140a5565b60405180910390f35b61056e600480360381019061056991906137dc565b611d2d565b60405161057c9291906140c0565b60405180910390f35b61059f600480360381019061059a91906140e9565b611dba565b6040516105ac91906130a8565b60405180910390f35b6105cf60048036038101906105ca91906141d9565b611ddd565b6040516105dc919061435f565b60405180910390f35b6105ed611f19565b6040516105fa9190613f59565b60405180910390f35b61061d60048036038101906106189190613f8f565b611f3c565b60405161062a91906130a8565b60405180910390f35b61064d600480360381019061064891906140e9565b611f54565b60405161065a9190613f74565b60405180910390f35b61067d60048036038101906106789190614381565b611f89565b60405161068a9190613f59565b60405180910390f35b6106ad60048036038101906106a891906137dc565b611fbd565b6040516106bb9291906143f8565b60405180910390f35b6106cc612019565b6040516106d99190613f74565b60405180910390f35b6106fc60048036038101906106f79190614421565b612036565b6040516107099190613fd7565b60405180910390f35b61071a6120f3565b6040516107279190613f74565b60405180910390f35b61073861212f565b005b6107426124b0565b60405161074f9190613fd7565b60405180910390f35b610772600480360381019061076d9190613f8f565b6124c0565b60405161077f9190613fd7565b60405180910390f35b6107a2600480360381019061079d9190613f8f565b6124f4565b6040516107af91906144b7565b60405180910390f35b6107d260048036038101906107cd91906144fe565b612531565b005b6107dc612628565b6040516107e99190613f59565b60405180910390f35b60008282604051602001610807929190614567565b60405160208183030381529060405280519060200120905092915050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156108b45750610884611bf7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156108eb576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160000160109054906101000a900460ff1615610935576040517f764c143b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018060000160106101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167fd4ae81319f0b4df100dcda9ce971671b97278c7a5ce6b37a8331a44700679fd460405160405180910390a2565b60007f436861696e000000000000000000000000000000000000000000000000000000905090565b6000610a11600260008781526020019081526020016000205484846040516020016109eb929190614567565b604051602081830303815290604052805190602001208661262d9092919063ffffffff16565b9050949350505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015610aaa5750610a7a611bf7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15610ae1576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b8152600401610b3a906145b1565b602060405180830381865afa158015610b57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7b91906145df565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610be2576040517f3a81d6fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610c1c5750610c27565b610c2581612644565b505b565b606060008267ffffffffffffffff811115610c4757610c46612eec565b5b604051908082528060200260200182016040528015610c755781602001602082028036833780820191505090505b50905060005b83811015610cc657600080602087600185010102905080880151915081848481518110610cab57610caa61460c565b5b60200260200101818152505050508080600101915050610c7b565b50809150509392505050565b6040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525081565b6060808383905067ffffffffffffffff811115610d2b57610d2a612eec565b5b604051908082528060200260200182016040528015610d595781602001602082028036833780820191505090505b5090508383905067ffffffffffffffff811115610d7957610d78612eec565b5b604051908082528060200260200182016040528015610da75781602001602082028036833780820191505090505b50915060005b84849050811015610ea257600060036000878785818110610dd157610dd061460c565b5b90506020020135815260200190815260200160002090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16848381518110610e4657610e4561460c565b5b60200260200101818152505080600001601c9054906101000a900463ffffffff16838381518110610e7a57610e7961460c565b5b602002602001019063ffffffff16908163ffffffff1681525050818060010192505050610dad565b509250929050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806000600360008581526020019081526020016000209050610f3b8160000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16612986565b81600001601c9054906101000a900463ffffffff168063ffffffff1690509250925050915091565b610f708161ffff16612a2e565b50565b610f828763ffffffff16612b79565b60008787604051602001610f97929190614692565b604051602081830303815290604052905060005b86518110156111a757858181518110610fc757610fc661460c565b5b6020026020010151868281518110610fe257610fe161460c565b5b60200260200101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff161461103f576040517f6980091000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604051806040016040528087838151811061105d5761105c61460c565b5b60200260200101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681526020018a63ffffffff16815250600360008984815181106110a9576110a861460c565b5b6020026020010151815260200190815260200160002060008201518160000160006101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff160217905550602082015181600001601c6101000a81548163ffffffff021916908363ffffffff160217905550905050818782815181106111545761115361460c565b5b602002602001015187838151811061116f5761116e61460c565b5b6020026020010151604051602001611189939291906146df565b60405160208183030381529060405291508080600101915050610fab565b506000806000838051906020012090506000805b88518110156113b7576000611220848b84815181106111dd576111dc61460c565b5b60200260200101518b85815181106111f8576111f761460c565b5b60200260200101518b86815181106112135761121261460c565b5b6020026020010151612036565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231836040518263ffffffff1660e01b815260040161127d9190613fd7565b602060405180830381865afa15801561129a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112be919061472d565b90508173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1610611325576040517f9079f69b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8193506000810361133f57828060010193505050506113b2565b868061134a90614789565b9750508173ffffffffffffffffffffffffffffffffffffffff168f63ffffffff167fbac7552ab5da8d0588709ddb75aceec28520646f54bca1cc5e6e104db61935ec8360405161139a9190613f59565b60405180910390a38086019550828060010193505050505b6111bb565b507f000000000000000000000000000000000000000000000000000000000000000061ffff16841015611416576040517fe246dc6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167f5f11830295067c4bcc7d02d4e3b048cd7427be50a3aeb6afc9d3d559ee64bcfa8d7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114de919061472d565b866040516114ee93929190614802565b60405180910390a28a600260008e63ffffffff168152602001908152602001600020819055508b600160000160086101000a81548163ffffffff021916908363ffffffff160217905550505050505050505050505050565b60008060001b830361155b5760009050611573565b61157083838661262d9092919063ffffffff16565b90505b9392505050565b6000806000806000806060806060600080600060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff1615151515815250509050439b5080606001519a50806040015198508899507f000000000000000000000000000000000000000000000000000000000000000091507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611715919061472d565b925060008067ffffffffffffffff81111561173357611732612eec565b5b6040519080825280602002602001820160405280156117615781602001602082028036833780820191505090505b5095508067ffffffffffffffff81111561177e5761177d612eec565b5b6040519080825280602002602001820160405280156117ac5781602001602082028036833780820191505090505b5096508067ffffffffffffffff8111156117c9576117c8612eec565b5b6040519080825280602002602001820160405280156117fc57816020015b60608152602001906001900390816117e75790505b50945060009850600182606001518b010197505050909192939495969798999a565b60008073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16036118ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118a590614896565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b8152600401611905906148dc565b602060405180830381865afa158015611922573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194691906145df565b905090565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b81526004016119a49061491b565b602060405180830381865afa1580156119c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e591906145df565b905090565b60006001905090565b6119fb612cf9565b73ffffffffffffffffffffffffffffffffffffffff16611a19611bf7565b73ffffffffffffffffffffffffffffffffffffffff1614611a6f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a6690614980565b60405180910390fd5b611a796000612d01565b565b6000600160000160009054906101000a900463ffffffff16600160000160049054906101000a900463ffffffff16611ab391906149a0565b63ffffffff16905090565b6000600160000160009054906101000a900463ffffffff16905090565b60008060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff161515151581525050905082816060015182604001510163ffffffff161015611bc15782915050611bca565b80604001519150505b919050565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000611c37600142611c3291906149d4565b6124c0565b905090565b611c44612e51565b60016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff161515151581525050905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060006003600085815260200190815260200160002090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681600001601c9054906101000a900463ffffffff168063ffffffff1690509250925050915091565b6000600260008363ffffffff168152602001908152602001600020549050919050565b6060815167ffffffffffffffff811115611dfa57611df9612eec565b5b604051908082528060200260200182016040528015611e285781602001602082028036833780820191505090505b5090506000805b8351811015611f0f57611ebe60026000898481518110611e5257611e5161460c565b5b602002602001015163ffffffff16815260200190815260200160002054858381518110611e8257611e8161460c565b5b6020026020010151611eaf89868a8781518110611ea257611ea161460c565b5b6020026020010151610c29565b61262d9092919063ffffffff16565b838281518110611ed157611ed061460c565b5b602002602001019015159081151581525050848181518110611ef657611ef561460c565b5b6020026020010151820191508080600101915050611e2f565b5050949350505050565b6000600160000160089054906101000a900463ffffffff1663ffffffff16905090565b60026020528060005260406000206000915090505481565b60008060001b600260008463ffffffff1681526020019081526020016000205414611f7f5781611f82565b60005b9050919050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60036020528060005260406000206000915090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169080600001601c9054906101000a900463ffffffff16905082565b6000600160000160089054906101000a900463ffffffff16905090565b6000806040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525086604051602001612081929190614a2a565b604051602081830303815290604052805190602001209050600181868686604051600081526020016040526040516120bc9493929190614a61565b6020604051602081039080840390855afa1580156120de573d6000803e3d6000fd5b50505060206040510351915050949350505050565b600080600160000160089054906101000a900463ffffffff1663ffffffff1603612120576000905061212c565b61212942611adb565b90505b90565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156121be575061218e611bf7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156121f5576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160000160109054906101000a900460ff166124ae5760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b8152600401612265906145b1565b602060405180830381865afa158015612282573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122a691906145df565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361230d576040517ff8e0084400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061244c573073ffffffffffffffffffffffffffffffffffffffff16636d046c3e6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561237d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123a19190614ad2565b15158173ffffffffffffffffffffffffffffffffffffffff16636d046c3e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124129190614ad2565b15151461244b576040517f07b72f5e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b60018060000160106101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167fd4ae81319f0b4df100dcda9ce971671b97278c7a5ce6b37a8331a44700679fd460405160405180910390a2505b565b60006124bb426124c0565b905090565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6124fc612e9a565b6040518060400160405280600260008581526020019081526020016000205481526020018363ffffffff168152509050919050565b612539612cf9565b73ffffffffffffffffffffffffffffffffffffffff16612557611bf7565b73ffffffffffffffffffffffffffffffffffffffff16146125ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125a490614980565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361261c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161261390614b71565b60405180910390fd5b61262581612d01565b50565b600281565b60008261263a8584612dc5565b1490509392505050565b6000808273ffffffffffffffffffffffffffffffffffffffff167fffa1ad74ba96b4c159a84d090433911c3991c54f629eb60d0c84aed3be5f067c60405160200161268f9190614bcc565b6040516020818303038152906040526040516126ab9190614be7565b600060405180830381855afa9150503d80600081146126e6576040519150601f19603f3d011682016040523d82523d6000602084013e6126eb565b606091505b50915091506000826126fe576001612713565b81806020019051810190612712919061472d565b5b9050600181036128935760008473ffffffffffffffffffffffffffffffffffffffff1663d3d3ea086040518163ffffffff1660e01b8152600401602060405180830381865afa15801561276a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061278e9190614c13565b90508473ffffffffffffffffffffffffffffffffffffffff1663c3369db8826040518263ffffffff1660e01b81526004016127c99190613f74565b602060405180830381865afa1580156127e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061280a9190614c13565b600160000160086101000a81548163ffffffff021916908363ffffffff16021790555060028161283a9190614c40565b600160000160046101000a81548163ffffffff021916908363ffffffff16021790555060028161286a9190614c40565b600160000160006101000a81548163ffffffff021916908363ffffffff16021790555050612980565b60008473ffffffffffffffffffffffffffffffffffffffff1663a0bc93746040518163ffffffff1660e01b815260040160a060405180830381865afa1580156128e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129049190614d0b565b90508060200151600160000160046101000a81548163ffffffff021916908363ffffffff1602179055508060200151600160000160006101000a81548163ffffffff021916908363ffffffff1602179055508060400151600160000160086101000a81548163ffffffff021916908363ffffffff160217905550505b50505050565b60008060007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff905060026001826129b99190614d38565b6129c39190614d9b565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1611612a185760008401915081601b0b92505050612a29565b600181850303915081601b0b925050505b919050565b612a36612cf9565b73ffffffffffffffffffffffffffffffffffffffff16612a54611bf7565b73ffffffffffffffffffffffffffffffffffffffff1614612aaa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612aa190614980565b60405180910390fd5b8063ffffffff166001600001600c9054906101000a900463ffffffff1663ffffffff1603612b04576040517f96f56f6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600001600c6101000a81548163ffffffff021916908363ffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167f02ff77a0f68d11f7efb906f331b2dda82916de8ba9c37dda2a95817936a530ec82604051612b6e9190613f74565b60405180910390a250565b600060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff16151515158152505090506000816040015163ffffffff1603612c81576040517f96a96e1700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81816060015182604001510163ffffffff1610612cca576040517ff886149e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001816020015101600160000160046101000a81548163ffffffff021916908363ffffffff1602179055505050565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60008082905060005b8451811015612e2f576000858281518110612dec57612deb61460c565b5b60200260200101519050808311612e0e57612e078382612e3a565b9250612e1b565b612e188184612e3a565b92505b508080612e2790614789565b915050612dce565b508091505092915050565b600082600052816020526040600020905092915050565b6040518060a00160405280600063ffffffff168152602001600063ffffffff168152602001600063ffffffff168152602001600063ffffffff1681526020016000151581525090565b604051806040016040528060008019168152602001600063ffffffff1681525090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612f2482612edb565b810181811067ffffffffffffffff82111715612f4357612f42612eec565b5b80604052505050565b6000612f56612ebd565b9050612f628282612f1b565b919050565b600067ffffffffffffffff821115612f8257612f81612eec565b5b612f8b82612edb565b9050602081019050919050565b82818337600083830152505050565b6000612fba612fb584612f67565b612f4c565b905082815260208101848484011115612fd657612fd5612ed6565b5b612fe1848285612f98565b509392505050565b600082601f830112612ffe57612ffd612ed1565b5b813561300e848260208601612fa7565b91505092915050565b6000806040838503121561302e5761302d612ec7565b5b600083013567ffffffffffffffff81111561304c5761304b612ecc565b5b61305885828601612fe9565b925050602083013567ffffffffffffffff81111561307957613078612ecc565b5b61308585828601612fe9565b9150509250929050565b6000819050919050565b6130a28161308f565b82525050565b60006020820190506130bd6000830184613099565b92915050565b6000819050919050565b6130d6816130c3565b81146130e157600080fd5b50565b6000813590506130f3816130cd565b92915050565b600067ffffffffffffffff82111561311457613113612eec565b5b602082029050602081019050919050565b600080fd5b6131338161308f565b811461313e57600080fd5b50565b6000813590506131508161312a565b92915050565b6000613169613164846130f9565b612f4c565b9050808382526020820190506020840283018581111561318c5761318b613125565b5b835b818110156131b557806131a18882613141565b84526020840193505060208101905061318e565b5050509392505050565b600082601f8301126131d4576131d3612ed1565b5b81356131e4848260208601613156565b91505092915050565b6000806000806080858703121561320757613206612ec7565b5b6000613215878288016130e4565b945050602085013567ffffffffffffffff81111561323657613235612ecc565b5b613242878288016131bf565b935050604085013567ffffffffffffffff81111561326357613262612ecc565b5b61326f87828801612fe9565b925050606085013567ffffffffffffffff8111156132905761328f612ecc565b5b61329c87828801612fe9565b91505092959194509250565b60008115159050919050565b6132bd816132a8565b82525050565b60006020820190506132d860008301846132b4565b92915050565b6000806000606084860312156132f7576132f6612ec7565b5b600084013567ffffffffffffffff81111561331557613314612ecc565b5b61332186828701612fe9565b9350506020613332868287016130e4565b9250506040613343868287016130e4565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6133828161308f565b82525050565b60006133948383613379565b60208301905092915050565b6000602082019050919050565b60006133b88261334d565b6133c28185613358565b93506133cd83613369565b8060005b838110156133fe5781516133e58882613388565b97506133f0836133a0565b9250506001810190506133d1565b5085935050505092915050565b6000602082019050818103600083015261342581846133ad565b905092915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561346757808201518184015260208101905061344c565b83811115613476576000848401525b50505050565b60006134878261342d565b6134918185613438565b93506134a1818560208601613449565b6134aa81612edb565b840191505092915050565b600060208201905081810360008301526134cf818461347c565b905092915050565b600080fd5b60008083601f8401126134f2576134f1612ed1565b5b8235905067ffffffffffffffff81111561350f5761350e6134d7565b5b60208301915083602082028301111561352b5761352a613125565b5b9250929050565b6000806020838503121561354957613548612ec7565b5b600083013567ffffffffffffffff81111561356757613566612ecc565b5b613573858286016134dc565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6135b4816130c3565b82525050565b60006135c683836135ab565b60208301905092915050565b6000602082019050919050565b60006135ea8261357f565b6135f4818561358a565b93506135ff8361359b565b8060005b8381101561363057815161361788826135ba565b9750613622836135d2565b925050600181019050613603565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600063ffffffff82169050919050565b61368281613669565b82525050565b60006136948383613679565b60208301905092915050565b6000602082019050919050565b60006136b88261363d565b6136c28185613648565b93506136cd83613659565b8060005b838110156136fe5781516136e58882613688565b97506136f0836136a0565b9250506001810190506136d1565b5085935050505092915050565b6000604082019050818103600083015261372581856135df565b9050818103602083015261373981846136ad565b90509392505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061378761378261377d84613742565b613762565b613742565b9050919050565b60006137998261376c565b9050919050565b60006137ab8261378e565b9050919050565b6137bb816137a0565b82525050565b60006020820190506137d660008301846137b2565b92915050565b6000602082840312156137f2576137f1612ec7565b5b600061380084828501613141565b91505092915050565b6000819050919050565b61381c81613809565b82525050565b61382b816130c3565b82525050565b60006040820190506138466000830185613813565b6138536020830184613822565b9392505050565b600061ffff82169050919050565b6138718161385a565b811461387c57600080fd5b50565b60008135905061388e81613868565b92915050565b6000602082840312156138aa576138a9612ec7565b5b60006138b88482850161387f565b91505092915050565b6138ca81613669565b81146138d557600080fd5b50565b6000813590506138e7816138c1565b92915050565b600067ffffffffffffffff82111561390857613907612eec565b5b602082029050602081019050919050565b600061392c613927846138ed565b612f4c565b9050808382526020820190506020840283018581111561394f5761394e613125565b5b835b81811015613978578061396488826130e4565b845260208401935050602081019050613951565b5050509392505050565b600082601f83011261399757613996612ed1565b5b81356139a7848260208601613919565b91505092915050565b600067ffffffffffffffff8211156139cb576139ca612eec565b5b602082029050602081019050919050565b600060ff82169050919050565b6139f2816139dc565b81146139fd57600080fd5b50565b600081359050613a0f816139e9565b92915050565b6000613a28613a23846139b0565b612f4c565b90508083825260208201905060208402830185811115613a4b57613a4a613125565b5b835b81811015613a745780613a608882613a00565b845260208401935050602081019050613a4d565b5050509392505050565b600082601f830112613a9357613a92612ed1565b5b8135613aa3848260208601613a15565b91505092915050565b600080600080600080600060e0888a031215613acb57613aca612ec7565b5b6000613ad98a828b016138d8565b9750506020613aea8a828b01613141565b965050604088013567ffffffffffffffff811115613b0b57613b0a612ecc565b5b613b178a828b016131bf565b955050606088013567ffffffffffffffff811115613b3857613b37612ecc565b5b613b448a828b01613982565b945050608088013567ffffffffffffffff811115613b6557613b64612ecc565b5b613b718a828b01613a7e565b93505060a088013567ffffffffffffffff811115613b9257613b91612ecc565b5b613b9e8a828b016131bf565b92505060c088013567ffffffffffffffff811115613bbf57613bbe612ecc565b5b613bcb8a828b016131bf565b91505092959891949750929550565b600080600060608486031215613bf357613bf2612ec7565b5b600084013567ffffffffffffffff811115613c1157613c10612ecc565b5b613c1d868287016131bf565b9350506020613c2e86828701613141565b9250506040613c3f86828701613141565b9150509250925092565b613c5281613669565b82525050565b6000613c6382613742565b9050919050565b613c7381613c58565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b613cae81613c58565b82525050565b6000613cc08383613ca5565b60208301905092915050565b6000602082019050919050565b6000613ce482613c79565b613cee8185613c84565b9350613cf983613c95565b8060005b83811015613d2a578151613d118882613cb4565b9750613d1c83613ccc565b925050600181019050613cfd565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b6000613d8a82613d63565b613d948185613d6e565b9350613da4818560208601613449565b613dad81612edb565b840191505092915050565b6000613dc48383613d7f565b905092915050565b6000602082019050919050565b6000613de482613d37565b613dee8185613d42565b935083602082028501613e0085613d53565b8060005b85811015613e3c5784840389528151613e1d8582613db8565b9450613e2883613dcc565b925060208a01995050600181019050613e04565b50829750879550505050505092915050565b613e578161385a565b82525050565b600061016082019050613e73600083018e613822565b613e80602083018d613c49565b613e8d604083018c613c49565b613e9a606083018b613c49565b613ea7608083018a613c6a565b613eb460a0830189613c49565b81810360c0830152613ec68188613cd9565b905081810360e0830152613eda81876135df565b9050818103610100830152613eef8186613dd9565b9050613eff610120830185613822565b613f0d610140830184613e4e565b9c9b505050505050505050505050565b6000613f288261378e565b9050919050565b613f3881613f1d565b82525050565b6000602082019050613f536000830184613f2f565b92915050565b6000602082019050613f6e6000830184613822565b92915050565b6000602082019050613f896000830184613c49565b92915050565b600060208284031215613fa557613fa4612ec7565b5b6000613fb3848285016130e4565b91505092915050565b6000602082019050613fd16000830184613e4e565b92915050565b6000602082019050613fec6000830184613c6a565b92915050565b613ffb816132a8565b82525050565b60a0820160008201516140176000850182613679565b50602082015161402a6020850182613679565b50604082015161403d6040850182613679565b5060608201516140506060850182613679565b5060808201516140636080850182613ff2565b50505050565b600060a08201905061407e6000830184614001565b92915050565b600061408f8261378e565b9050919050565b61409f81614084565b82525050565b60006020820190506140ba6000830184614096565b92915050565b60006040820190506140d56000830185613822565b6140e26020830184613822565b9392505050565b6000602082840312156140ff576140fe612ec7565b5b600061410d848285016138d8565b91505092915050565b600067ffffffffffffffff82111561413157614130612eec565b5b602082029050602081019050919050565b600061415561415084614116565b612f4c565b9050808382526020820190506020840283018581111561417857614177613125565b5b835b818110156141a1578061418d88826138d8565b84526020840193505060208101905061417a565b5050509392505050565b600082601f8301126141c0576141bf612ed1565b5b81356141d0848260208601614142565b91505092915050565b600080600080608085870312156141f3576141f2612ec7565b5b600085013567ffffffffffffffff81111561421157614210612ecc565b5b61421d878288016141ab565b945050602085013567ffffffffffffffff81111561423e5761423d612ecc565b5b61424a87828801612fe9565b935050604085013567ffffffffffffffff81111561426b5761426a612ecc565b5b61427787828801613982565b925050606085013567ffffffffffffffff81111561429857614297612ecc565b5b6142a4878288016131bf565b91505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60006142e88383613ff2565b60208301905092915050565b6000602082019050919050565b600061430c826142b0565b61431681856142bb565b9350614321836142cc565b8060005b8381101561435257815161433988826142dc565b9750614344836142f4565b925050600181019050614325565b5085935050505092915050565b600060208201905081810360008301526143798184614301565b905092915050565b6000806040838503121561439857614397612ec7565b5b60006143a6858286016130e4565b92505060206143b7858286016130e4565b9150509250929050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff82169050919050565b6143f2816143c1565b82525050565b600060408201905061440d60008301856143e9565b61441a6020830184613c49565b9392505050565b6000806000806080858703121561443b5761443a612ec7565b5b600061444987828801613141565b945050602061445a87828801613a00565b935050604061446b87828801613141565b925050606061447c87828801613141565b91505092959194509250565b60408201600082015161449e6000850182613379565b5060208201516144b16020850182613679565b50505050565b60006040820190506144cc6000830184614488565b92915050565b6144db81613c58565b81146144e657600080fd5b50565b6000813590506144f8816144d2565b92915050565b60006020828403121561451457614513612ec7565b5b6000614522848285016144e9565b91505092915050565b600081905092915050565b60006145418261342d565b61454b818561452b565b935061455b818560208601613449565b80840191505092915050565b60006145738285614536565b915061457f8284614536565b91508190509392505050565b7f436861696e000000000000000000000000000000000000000000000000000000815250565b60006020820190506145c56000830161458b565b919050565b6000815190506145d9816144d2565b92915050565b6000602082840312156145f5576145f4612ec7565b5b6000614603848285016145ca565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008160e01b9050919050565b60006146538261463b565b9050919050565b61466b61466682613669565b614648565b82525050565b6000819050919050565b61468c6146878261308f565b614671565b82525050565b600061469e828561465a565b6004820191506146ae828461467b565b6020820191508190509392505050565b6000819050919050565b6146d96146d4826130c3565b6146be565b82525050565b60006146eb8286614536565b91506146f7828561467b565b60208201915061470782846146c8565b602082019150819050949350505050565b600081519050614727816130cd565b92915050565b60006020828403121561474357614742612ec7565b5b600061475184828501614718565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614794826130c3565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036147c6576147c561475a565b5b600182019050919050565b60006147ec6147e76147e284613669565b613762565b6130c3565b9050919050565b6147fc816147d1565b82525050565b600060608201905061481760008301866147f3565b6148246020830185613822565b6148316040830184613822565b949350505050565b600082825260208201905092915050565b7f5f726567697374727920697320656d7074790000000000000000000000000000600082015250565b6000614880601283614839565b915061488b8261484a565b602082019050919050565b600060208201905081810360008301526148af81614873565b9050919050565b7f554d420000000000000000000000000000000000000000000000000000000000815250565b60006020820190506148f0600083016148b6565b919050565b7f5374616b696e6742616e6b000000000000000000000000000000000000000000815250565b600060208201905061492f600083016148f5565b919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600061496a602083614839565b915061497582614934565b602082019050919050565b600060208201905081810360008301526149998161495d565b9050919050565b60006149ab82613669565b91506149b683613669565b9250828210156149c9576149c861475a565b5b828203905092915050565b60006149df826130c3565b91506149ea836130c3565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115614a1f57614a1e61475a565b5b828201905092915050565b6000614a368285614536565b9150614a42828461467b565b6020820191508190509392505050565b614a5b816139dc565b82525050565b6000608082019050614a766000830187613099565b614a836020830186614a52565b614a906040830185613099565b614a9d6060830184613099565b95945050505050565b614aaf816132a8565b8114614aba57600080fd5b50565b600081519050614acc81614aa6565b92915050565b600060208284031215614ae857614ae7612ec7565b5b6000614af684828501614abd565b91505092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000614b5b602683614839565b9150614b6682614aff565b604082019050919050565b60006020820190508181036000830152614b8a81614b4e565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b614bc681614b91565b82525050565b6000602082019050614be16000830184614bbd565b92915050565b6000614bf38284614536565b915081905092915050565b600081519050614c0d816138c1565b92915050565b600060208284031215614c2957614c28612ec7565b5b6000614c3784828501614bfe565b91505092915050565b6000614c4b82613669565b9150614c5683613669565b92508263ffffffff03821115614c6f57614c6e61475a565b5b828201905092915050565b600080fd5b600060a08284031215614c9557614c94614c7a565b5b614c9f60a0612f4c565b90506000614caf84828501614bfe565b6000830152506020614cc384828501614bfe565b6020830152506040614cd784828501614bfe565b6040830152506060614ceb84828501614bfe565b6060830152506080614cff84828501614abd565b60808301525092915050565b600060a08284031215614d2157614d20612ec7565b5b6000614d2f84828501614c7f565b91505092915050565b6000614d43826143c1565b9150614d4e836143c1565b925082821015614d6157614d6061475a565b5b828203905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614da6826143c1565b9150614db1836143c1565b925082614dc157614dc0614d6c565b5b82820490509291505056fea2646970667358221220c360ae03d3a676b33b3c5097d3c8e8893865decc08d54266712bbb98da90469d64736f6c634300080d0033", "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101f95760003560e01c80630f2acc3e146101fe5780630fcc0c281461022e57806317d7de7c14610238578063199dadc5146102565780631aa3a00814610286578063243b68f91461029057806324c89a49146102c057806326f3ab8b146102de57806334ba34811461030f5780633bb8819d1461032d57806340a9e5e31461035e578063485e055d1461037a5780634bc935d7146103965780634e69d560146103c657806355a373d6146103ee578063637180a81461040c5780636d046c3e1461042a578063715018a6146104485780637353cbcb1461045257806377839fe614610470578063805d34321461048e5780638d068043146104be5780638da5cb5b146104dc5780639f6119d7146104fa578063a0bc937414610518578063abf410e514610536578063adf1639d14610554578063bef9f8a114610585578063bf66e3ba146105b5578063c2a4250b146105e5578063c2b40ae414610603578063c3369db814610633578063ca4d29d214610663578063cbb1b2c714610693578063d3d3ea08146106c4578063d45167d0146106e2578063e76c0b5714610712578063e79a198f14610730578063ed9975c31461073a578063ef19f3e714610758578063f25b3f9914610788578063f2fde38b146107b8578063ffa1ad74146107d4575b600080fd5b61021860048036038101906102139190613017565b6107f2565b60405161022591906130a8565b60405180910390f35b610236610825565b005b610240610997565b60405161024d91906130a8565b60405180910390f35b610270600480360381019061026b91906131ed565b6109bf565b60405161027d91906132c3565b60405180910390f35b61028e610a1b565b005b6102aa60048036038101906102a591906132de565b610c29565b6040516102b7919061340b565b60405180910390f35b6102c8610cd2565b6040516102d591906134b5565b60405180910390f35b6102f860048036038101906102f39190613532565b610d0b565b60405161030692919061370b565b60405180910390f35b610317610eaa565b60405161032491906137c1565b60405180910390f35b610347600480360381019061034291906137dc565b610ece565b604051610355929190613831565b60405180910390f35b61037860048036038101906103739190613894565b610f63565b005b610394600480360381019061038f9190613aac565b610f73565b005b6103b060048036038101906103ab9190613bda565b611546565b6040516103bd91906132c3565b60405180910390f35b6103ce61157a565b6040516103e59b9a99989796959493929190613e5d565b60405180910390f35b6103f661181e565b6040516104039190613f3e565b60405180910390f35b61041461194b565b60405161042191906137c1565b60405180910390f35b6104326119ea565b60405161043f91906132c3565b60405180910390f35b6104506119f3565b005b61045a611a7b565b6040516104679190613f59565b60405180910390f35b610478611abe565b6040516104859190613f74565b60405180910390f35b6104a860048036038101906104a39190613f8f565b611adb565b6040516104b59190613f74565b60405180910390f35b6104c6611bcf565b6040516104d39190613fbc565b60405180910390f35b6104e4611bf7565b6040516104f19190613fd7565b60405180910390f35b610502611c20565b60405161050f9190613fd7565b60405180910390f35b610520611c3c565b60405161052d9190614069565b60405180910390f35b61053e611d09565b60405161054b91906140a5565b60405180910390f35b61056e600480360381019061056991906137dc565b611d2d565b60405161057c9291906140c0565b60405180910390f35b61059f600480360381019061059a91906140e9565b611dba565b6040516105ac91906130a8565b60405180910390f35b6105cf60048036038101906105ca91906141d9565b611ddd565b6040516105dc919061435f565b60405180910390f35b6105ed611f19565b6040516105fa9190613f59565b60405180910390f35b61061d60048036038101906106189190613f8f565b611f3c565b60405161062a91906130a8565b60405180910390f35b61064d600480360381019061064891906140e9565b611f54565b60405161065a9190613f74565b60405180910390f35b61067d60048036038101906106789190614381565b611f89565b60405161068a9190613f59565b60405180910390f35b6106ad60048036038101906106a891906137dc565b611fbd565b6040516106bb9291906143f8565b60405180910390f35b6106cc612019565b6040516106d99190613f74565b60405180910390f35b6106fc60048036038101906106f79190614421565b612036565b6040516107099190613fd7565b60405180910390f35b61071a6120f3565b6040516107279190613f74565b60405180910390f35b61073861212f565b005b6107426124b0565b60405161074f9190613fd7565b60405180910390f35b610772600480360381019061076d9190613f8f565b6124c0565b60405161077f9190613fd7565b60405180910390f35b6107a2600480360381019061079d9190613f8f565b6124f4565b6040516107af91906144b7565b60405180910390f35b6107d260048036038101906107cd91906144fe565b612531565b005b6107dc612628565b6040516107e99190613f59565b60405180910390f35b60008282604051602001610807929190614567565b60405160208183030381529060405280519060200120905092915050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156108b45750610884611bf7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156108eb576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160000160109054906101000a900460ff1615610935576040517f764c143b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018060000160106101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167fd4ae81319f0b4df100dcda9ce971671b97278c7a5ce6b37a8331a44700679fd460405160405180910390a2565b60007f436861696e000000000000000000000000000000000000000000000000000000905090565b6000610a11600260008781526020019081526020016000205484846040516020016109eb929190614567565b604051602081830303815290604052805190602001208661262d9092919063ffffffff16565b9050949350505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015610aaa5750610a7a611bf7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15610ae1576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b8152600401610b3a906145b1565b602060405180830381865afa158015610b57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7b91906145df565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610be2576040517f3a81d6fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610c1c5750610c27565b610c2581612644565b505b565b606060008267ffffffffffffffff811115610c4757610c46612eec565b5b604051908082528060200260200182016040528015610c755781602001602082028036833780820191505090505b50905060005b83811015610cc657600080602087600185010102905080880151915081848481518110610cab57610caa61460c565b5b60200260200101818152505050508080600101915050610c7b565b50809150509392505050565b6040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525081565b6060808383905067ffffffffffffffff811115610d2b57610d2a612eec565b5b604051908082528060200260200182016040528015610d595781602001602082028036833780820191505090505b5090508383905067ffffffffffffffff811115610d7957610d78612eec565b5b604051908082528060200260200182016040528015610da75781602001602082028036833780820191505090505b50915060005b84849050811015610ea257600060036000878785818110610dd157610dd061460c565b5b90506020020135815260200190815260200160002090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16848381518110610e4657610e4561460c565b5b60200260200101818152505080600001601c9054906101000a900463ffffffff16838381518110610e7a57610e7961460c565b5b602002602001019063ffffffff16908163ffffffff1681525050818060010192505050610dad565b509250929050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806000600360008581526020019081526020016000209050610f3b8160000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16612986565b81600001601c9054906101000a900463ffffffff168063ffffffff1690509250925050915091565b610f708161ffff16612a2e565b50565b610f828763ffffffff16612b79565b60008787604051602001610f97929190614692565b604051602081830303815290604052905060005b86518110156111a757858181518110610fc757610fc661460c565b5b6020026020010151868281518110610fe257610fe161460c565b5b60200260200101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff161461103f576040517f6980091000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604051806040016040528087838151811061105d5761105c61460c565b5b60200260200101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681526020018a63ffffffff16815250600360008984815181106110a9576110a861460c565b5b6020026020010151815260200190815260200160002060008201518160000160006101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff160217905550602082015181600001601c6101000a81548163ffffffff021916908363ffffffff160217905550905050818782815181106111545761115361460c565b5b602002602001015187838151811061116f5761116e61460c565b5b6020026020010151604051602001611189939291906146df565b60405160208183030381529060405291508080600101915050610fab565b506000806000838051906020012090506000805b88518110156113b7576000611220848b84815181106111dd576111dc61460c565b5b60200260200101518b85815181106111f8576111f761460c565b5b60200260200101518b86815181106112135761121261460c565b5b6020026020010151612036565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231836040518263ffffffff1660e01b815260040161127d9190613fd7565b602060405180830381865afa15801561129a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112be919061472d565b90508173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1610611325576040517f9079f69b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8193506000810361133f57828060010193505050506113b2565b868061134a90614789565b9750508173ffffffffffffffffffffffffffffffffffffffff168f63ffffffff167fbac7552ab5da8d0588709ddb75aceec28520646f54bca1cc5e6e104db61935ec8360405161139a9190613f59565b60405180910390a38086019550828060010193505050505b6111bb565b507f000000000000000000000000000000000000000000000000000000000000000061ffff16841015611416576040517fe246dc6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167f5f11830295067c4bcc7d02d4e3b048cd7427be50a3aeb6afc9d3d559ee64bcfa8d7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114de919061472d565b866040516114ee93929190614802565b60405180910390a28a600260008e63ffffffff168152602001908152602001600020819055508b600160000160086101000a81548163ffffffff021916908363ffffffff160217905550505050505050505050505050565b60008060001b830361155b5760009050611573565b61157083838661262d9092919063ffffffff16565b90505b9392505050565b6000806000806000806060806060600080600060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff1615151515815250509050439b5080606001519a50806040015198508899507f000000000000000000000000000000000000000000000000000000000000000091507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611715919061472d565b925060008067ffffffffffffffff81111561173357611732612eec565b5b6040519080825280602002602001820160405280156117615781602001602082028036833780820191505090505b5095508067ffffffffffffffff81111561177e5761177d612eec565b5b6040519080825280602002602001820160405280156117ac5781602001602082028036833780820191505090505b5096508067ffffffffffffffff8111156117c9576117c8612eec565b5b6040519080825280602002602001820160405280156117fc57816020015b60608152602001906001900390816117e75790505b50945060009850600182606001518b010197505050909192939495969798999a565b60008073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16036118ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118a590614896565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b8152600401611905906148dc565b602060405180830381865afa158015611922573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194691906145df565b905090565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b81526004016119a49061491b565b602060405180830381865afa1580156119c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e591906145df565b905090565b60006001905090565b6119fb612cf9565b73ffffffffffffffffffffffffffffffffffffffff16611a19611bf7565b73ffffffffffffffffffffffffffffffffffffffff1614611a6f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a6690614980565b60405180910390fd5b611a796000612d01565b565b6000600160000160009054906101000a900463ffffffff16600160000160049054906101000a900463ffffffff16611ab391906149a0565b63ffffffff16905090565b6000600160000160009054906101000a900463ffffffff16905090565b60008060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff161515151581525050905082816060015182604001510163ffffffff161015611bc15782915050611bca565b80604001519150505b919050565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000611c37600142611c3291906149d4565b6124c0565b905090565b611c44612e51565b60016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff161515151581525050905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060006003600085815260200190815260200160002090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681600001601c9054906101000a900463ffffffff168063ffffffff1690509250925050915091565b6000600260008363ffffffff168152602001908152602001600020549050919050565b6060815167ffffffffffffffff811115611dfa57611df9612eec565b5b604051908082528060200260200182016040528015611e285781602001602082028036833780820191505090505b5090506000805b8351811015611f0f57611ebe60026000898481518110611e5257611e5161460c565b5b602002602001015163ffffffff16815260200190815260200160002054858381518110611e8257611e8161460c565b5b6020026020010151611eaf89868a8781518110611ea257611ea161460c565b5b6020026020010151610c29565b61262d9092919063ffffffff16565b838281518110611ed157611ed061460c565b5b602002602001019015159081151581525050848181518110611ef657611ef561460c565b5b6020026020010151820191508080600101915050611e2f565b5050949350505050565b6000600160000160089054906101000a900463ffffffff1663ffffffff16905090565b60026020528060005260406000206000915090505481565b60008060001b600260008463ffffffff1681526020019081526020016000205414611f7f5781611f82565b60005b9050919050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60036020528060005260406000206000915090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169080600001601c9054906101000a900463ffffffff16905082565b6000600160000160089054906101000a900463ffffffff16905090565b6000806040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525086604051602001612081929190614a2a565b604051602081830303815290604052805190602001209050600181868686604051600081526020016040526040516120bc9493929190614a61565b6020604051602081039080840390855afa1580156120de573d6000803e3d6000fd5b50505060206040510351915050949350505050565b600080600160000160089054906101000a900463ffffffff1663ffffffff1603612120576000905061212c565b61212942611adb565b90505b90565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156121be575061218e611bf7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156121f5576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160000160109054906101000a900460ff166124ae5760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b8152600401612265906145b1565b602060405180830381865afa158015612282573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122a691906145df565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361230d576040517ff8e0084400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061244c573073ffffffffffffffffffffffffffffffffffffffff16636d046c3e6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561237d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123a19190614ad2565b15158173ffffffffffffffffffffffffffffffffffffffff16636d046c3e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124129190614ad2565b15151461244b576040517f07b72f5e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b60018060000160106101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167fd4ae81319f0b4df100dcda9ce971671b97278c7a5ce6b37a8331a44700679fd460405160405180910390a2505b565b60006124bb426124c0565b905090565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6124fc612e9a565b6040518060400160405280600260008581526020019081526020016000205481526020018363ffffffff168152509050919050565b612539612cf9565b73ffffffffffffffffffffffffffffffffffffffff16612557611bf7565b73ffffffffffffffffffffffffffffffffffffffff16146125ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125a490614980565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361261c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161261390614b71565b60405180910390fd5b61262581612d01565b50565b600281565b60008261263a8584612dc5565b1490509392505050565b6000808273ffffffffffffffffffffffffffffffffffffffff167fffa1ad74ba96b4c159a84d090433911c3991c54f629eb60d0c84aed3be5f067c60405160200161268f9190614bcc565b6040516020818303038152906040526040516126ab9190614be7565b600060405180830381855afa9150503d80600081146126e6576040519150601f19603f3d011682016040523d82523d6000602084013e6126eb565b606091505b50915091506000826126fe576001612713565b81806020019051810190612712919061472d565b5b9050600181036128935760008473ffffffffffffffffffffffffffffffffffffffff1663d3d3ea086040518163ffffffff1660e01b8152600401602060405180830381865afa15801561276a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061278e9190614c13565b90508473ffffffffffffffffffffffffffffffffffffffff1663c3369db8826040518263ffffffff1660e01b81526004016127c99190613f74565b602060405180830381865afa1580156127e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061280a9190614c13565b600160000160086101000a81548163ffffffff021916908363ffffffff16021790555060028161283a9190614c40565b600160000160046101000a81548163ffffffff021916908363ffffffff16021790555060028161286a9190614c40565b600160000160006101000a81548163ffffffff021916908363ffffffff16021790555050612980565b60008473ffffffffffffffffffffffffffffffffffffffff1663a0bc93746040518163ffffffff1660e01b815260040160a060405180830381865afa1580156128e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129049190614d0b565b90508060200151600160000160046101000a81548163ffffffff021916908363ffffffff1602179055508060200151600160000160006101000a81548163ffffffff021916908363ffffffff1602179055508060400151600160000160086101000a81548163ffffffff021916908363ffffffff160217905550505b50505050565b60008060007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff905060026001826129b99190614d38565b6129c39190614d9b565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1611612a185760008401915081601b0b92505050612a29565b600181850303915081601b0b925050505b919050565b612a36612cf9565b73ffffffffffffffffffffffffffffffffffffffff16612a54611bf7565b73ffffffffffffffffffffffffffffffffffffffff1614612aaa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612aa190614980565b60405180910390fd5b8063ffffffff166001600001600c9054906101000a900463ffffffff1663ffffffff1603612b04576040517f96f56f6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600001600c6101000a81548163ffffffff021916908363ffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167f02ff77a0f68d11f7efb906f331b2dda82916de8ba9c37dda2a95817936a530ec82604051612b6e9190613f74565b60405180910390a250565b600060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff16151515158152505090506000816040015163ffffffff1603612c81576040517f96a96e1700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81816060015182604001510163ffffffff1610612cca576040517ff886149e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001816020015101600160000160046101000a81548163ffffffff021916908363ffffffff1602179055505050565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60008082905060005b8451811015612e2f576000858281518110612dec57612deb61460c565b5b60200260200101519050808311612e0e57612e078382612e3a565b9250612e1b565b612e188184612e3a565b92505b508080612e2790614789565b915050612dce565b508091505092915050565b600082600052816020526040600020905092915050565b6040518060a00160405280600063ffffffff168152602001600063ffffffff168152602001600063ffffffff168152602001600063ffffffff1681526020016000151581525090565b604051806040016040528060008019168152602001600063ffffffff1681525090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612f2482612edb565b810181811067ffffffffffffffff82111715612f4357612f42612eec565b5b80604052505050565b6000612f56612ebd565b9050612f628282612f1b565b919050565b600067ffffffffffffffff821115612f8257612f81612eec565b5b612f8b82612edb565b9050602081019050919050565b82818337600083830152505050565b6000612fba612fb584612f67565b612f4c565b905082815260208101848484011115612fd657612fd5612ed6565b5b612fe1848285612f98565b509392505050565b600082601f830112612ffe57612ffd612ed1565b5b813561300e848260208601612fa7565b91505092915050565b6000806040838503121561302e5761302d612ec7565b5b600083013567ffffffffffffffff81111561304c5761304b612ecc565b5b61305885828601612fe9565b925050602083013567ffffffffffffffff81111561307957613078612ecc565b5b61308585828601612fe9565b9150509250929050565b6000819050919050565b6130a28161308f565b82525050565b60006020820190506130bd6000830184613099565b92915050565b6000819050919050565b6130d6816130c3565b81146130e157600080fd5b50565b6000813590506130f3816130cd565b92915050565b600067ffffffffffffffff82111561311457613113612eec565b5b602082029050602081019050919050565b600080fd5b6131338161308f565b811461313e57600080fd5b50565b6000813590506131508161312a565b92915050565b6000613169613164846130f9565b612f4c565b9050808382526020820190506020840283018581111561318c5761318b613125565b5b835b818110156131b557806131a18882613141565b84526020840193505060208101905061318e565b5050509392505050565b600082601f8301126131d4576131d3612ed1565b5b81356131e4848260208601613156565b91505092915050565b6000806000806080858703121561320757613206612ec7565b5b6000613215878288016130e4565b945050602085013567ffffffffffffffff81111561323657613235612ecc565b5b613242878288016131bf565b935050604085013567ffffffffffffffff81111561326357613262612ecc565b5b61326f87828801612fe9565b925050606085013567ffffffffffffffff8111156132905761328f612ecc565b5b61329c87828801612fe9565b91505092959194509250565b60008115159050919050565b6132bd816132a8565b82525050565b60006020820190506132d860008301846132b4565b92915050565b6000806000606084860312156132f7576132f6612ec7565b5b600084013567ffffffffffffffff81111561331557613314612ecc565b5b61332186828701612fe9565b9350506020613332868287016130e4565b9250506040613343868287016130e4565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6133828161308f565b82525050565b60006133948383613379565b60208301905092915050565b6000602082019050919050565b60006133b88261334d565b6133c28185613358565b93506133cd83613369565b8060005b838110156133fe5781516133e58882613388565b97506133f0836133a0565b9250506001810190506133d1565b5085935050505092915050565b6000602082019050818103600083015261342581846133ad565b905092915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561346757808201518184015260208101905061344c565b83811115613476576000848401525b50505050565b60006134878261342d565b6134918185613438565b93506134a1818560208601613449565b6134aa81612edb565b840191505092915050565b600060208201905081810360008301526134cf818461347c565b905092915050565b600080fd5b60008083601f8401126134f2576134f1612ed1565b5b8235905067ffffffffffffffff81111561350f5761350e6134d7565b5b60208301915083602082028301111561352b5761352a613125565b5b9250929050565b6000806020838503121561354957613548612ec7565b5b600083013567ffffffffffffffff81111561356757613566612ecc565b5b613573858286016134dc565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6135b4816130c3565b82525050565b60006135c683836135ab565b60208301905092915050565b6000602082019050919050565b60006135ea8261357f565b6135f4818561358a565b93506135ff8361359b565b8060005b8381101561363057815161361788826135ba565b9750613622836135d2565b925050600181019050613603565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600063ffffffff82169050919050565b61368281613669565b82525050565b60006136948383613679565b60208301905092915050565b6000602082019050919050565b60006136b88261363d565b6136c28185613648565b93506136cd83613659565b8060005b838110156136fe5781516136e58882613688565b97506136f0836136a0565b9250506001810190506136d1565b5085935050505092915050565b6000604082019050818103600083015261372581856135df565b9050818103602083015261373981846136ad565b90509392505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061378761378261377d84613742565b613762565b613742565b9050919050565b60006137998261376c565b9050919050565b60006137ab8261378e565b9050919050565b6137bb816137a0565b82525050565b60006020820190506137d660008301846137b2565b92915050565b6000602082840312156137f2576137f1612ec7565b5b600061380084828501613141565b91505092915050565b6000819050919050565b61381c81613809565b82525050565b61382b816130c3565b82525050565b60006040820190506138466000830185613813565b6138536020830184613822565b9392505050565b600061ffff82169050919050565b6138718161385a565b811461387c57600080fd5b50565b60008135905061388e81613868565b92915050565b6000602082840312156138aa576138a9612ec7565b5b60006138b88482850161387f565b91505092915050565b6138ca81613669565b81146138d557600080fd5b50565b6000813590506138e7816138c1565b92915050565b600067ffffffffffffffff82111561390857613907612eec565b5b602082029050602081019050919050565b600061392c613927846138ed565b612f4c565b9050808382526020820190506020840283018581111561394f5761394e613125565b5b835b81811015613978578061396488826130e4565b845260208401935050602081019050613951565b5050509392505050565b600082601f83011261399757613996612ed1565b5b81356139a7848260208601613919565b91505092915050565b600067ffffffffffffffff8211156139cb576139ca612eec565b5b602082029050602081019050919050565b600060ff82169050919050565b6139f2816139dc565b81146139fd57600080fd5b50565b600081359050613a0f816139e9565b92915050565b6000613a28613a23846139b0565b612f4c565b90508083825260208201905060208402830185811115613a4b57613a4a613125565b5b835b81811015613a745780613a608882613a00565b845260208401935050602081019050613a4d565b5050509392505050565b600082601f830112613a9357613a92612ed1565b5b8135613aa3848260208601613a15565b91505092915050565b600080600080600080600060e0888a031215613acb57613aca612ec7565b5b6000613ad98a828b016138d8565b9750506020613aea8a828b01613141565b965050604088013567ffffffffffffffff811115613b0b57613b0a612ecc565b5b613b178a828b016131bf565b955050606088013567ffffffffffffffff811115613b3857613b37612ecc565b5b613b448a828b01613982565b945050608088013567ffffffffffffffff811115613b6557613b64612ecc565b5b613b718a828b01613a7e565b93505060a088013567ffffffffffffffff811115613b9257613b91612ecc565b5b613b9e8a828b016131bf565b92505060c088013567ffffffffffffffff811115613bbf57613bbe612ecc565b5b613bcb8a828b016131bf565b91505092959891949750929550565b600080600060608486031215613bf357613bf2612ec7565b5b600084013567ffffffffffffffff811115613c1157613c10612ecc565b5b613c1d868287016131bf565b9350506020613c2e86828701613141565b9250506040613c3f86828701613141565b9150509250925092565b613c5281613669565b82525050565b6000613c6382613742565b9050919050565b613c7381613c58565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b613cae81613c58565b82525050565b6000613cc08383613ca5565b60208301905092915050565b6000602082019050919050565b6000613ce482613c79565b613cee8185613c84565b9350613cf983613c95565b8060005b83811015613d2a578151613d118882613cb4565b9750613d1c83613ccc565b925050600181019050613cfd565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b6000613d8a82613d63565b613d948185613d6e565b9350613da4818560208601613449565b613dad81612edb565b840191505092915050565b6000613dc48383613d7f565b905092915050565b6000602082019050919050565b6000613de482613d37565b613dee8185613d42565b935083602082028501613e0085613d53565b8060005b85811015613e3c5784840389528151613e1d8582613db8565b9450613e2883613dcc565b925060208a01995050600181019050613e04565b50829750879550505050505092915050565b613e578161385a565b82525050565b600061016082019050613e73600083018e613822565b613e80602083018d613c49565b613e8d604083018c613c49565b613e9a606083018b613c49565b613ea7608083018a613c6a565b613eb460a0830189613c49565b81810360c0830152613ec68188613cd9565b905081810360e0830152613eda81876135df565b9050818103610100830152613eef8186613dd9565b9050613eff610120830185613822565b613f0d610140830184613e4e565b9c9b505050505050505050505050565b6000613f288261378e565b9050919050565b613f3881613f1d565b82525050565b6000602082019050613f536000830184613f2f565b92915050565b6000602082019050613f6e6000830184613822565b92915050565b6000602082019050613f896000830184613c49565b92915050565b600060208284031215613fa557613fa4612ec7565b5b6000613fb3848285016130e4565b91505092915050565b6000602082019050613fd16000830184613e4e565b92915050565b6000602082019050613fec6000830184613c6a565b92915050565b613ffb816132a8565b82525050565b60a0820160008201516140176000850182613679565b50602082015161402a6020850182613679565b50604082015161403d6040850182613679565b5060608201516140506060850182613679565b5060808201516140636080850182613ff2565b50505050565b600060a08201905061407e6000830184614001565b92915050565b600061408f8261378e565b9050919050565b61409f81614084565b82525050565b60006020820190506140ba6000830184614096565b92915050565b60006040820190506140d56000830185613822565b6140e26020830184613822565b9392505050565b6000602082840312156140ff576140fe612ec7565b5b600061410d848285016138d8565b91505092915050565b600067ffffffffffffffff82111561413157614130612eec565b5b602082029050602081019050919050565b600061415561415084614116565b612f4c565b9050808382526020820190506020840283018581111561417857614177613125565b5b835b818110156141a1578061418d88826138d8565b84526020840193505060208101905061417a565b5050509392505050565b600082601f8301126141c0576141bf612ed1565b5b81356141d0848260208601614142565b91505092915050565b600080600080608085870312156141f3576141f2612ec7565b5b600085013567ffffffffffffffff81111561421157614210612ecc565b5b61421d878288016141ab565b945050602085013567ffffffffffffffff81111561423e5761423d612ecc565b5b61424a87828801612fe9565b935050604085013567ffffffffffffffff81111561426b5761426a612ecc565b5b61427787828801613982565b925050606085013567ffffffffffffffff81111561429857614297612ecc565b5b6142a4878288016131bf565b91505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60006142e88383613ff2565b60208301905092915050565b6000602082019050919050565b600061430c826142b0565b61431681856142bb565b9350614321836142cc565b8060005b8381101561435257815161433988826142dc565b9750614344836142f4565b925050600181019050614325565b5085935050505092915050565b600060208201905081810360008301526143798184614301565b905092915050565b6000806040838503121561439857614397612ec7565b5b60006143a6858286016130e4565b92505060206143b7858286016130e4565b9150509250929050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff82169050919050565b6143f2816143c1565b82525050565b600060408201905061440d60008301856143e9565b61441a6020830184613c49565b9392505050565b6000806000806080858703121561443b5761443a612ec7565b5b600061444987828801613141565b945050602061445a87828801613a00565b935050604061446b87828801613141565b925050606061447c87828801613141565b91505092959194509250565b60408201600082015161449e6000850182613379565b5060208201516144b16020850182613679565b50505050565b60006040820190506144cc6000830184614488565b92915050565b6144db81613c58565b81146144e657600080fd5b50565b6000813590506144f8816144d2565b92915050565b60006020828403121561451457614513612ec7565b5b6000614522848285016144e9565b91505092915050565b600081905092915050565b60006145418261342d565b61454b818561452b565b935061455b818560208601613449565b80840191505092915050565b60006145738285614536565b915061457f8284614536565b91508190509392505050565b7f436861696e000000000000000000000000000000000000000000000000000000815250565b60006020820190506145c56000830161458b565b919050565b6000815190506145d9816144d2565b92915050565b6000602082840312156145f5576145f4612ec7565b5b6000614603848285016145ca565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008160e01b9050919050565b60006146538261463b565b9050919050565b61466b61466682613669565b614648565b82525050565b6000819050919050565b61468c6146878261308f565b614671565b82525050565b600061469e828561465a565b6004820191506146ae828461467b565b6020820191508190509392505050565b6000819050919050565b6146d96146d4826130c3565b6146be565b82525050565b60006146eb8286614536565b91506146f7828561467b565b60208201915061470782846146c8565b602082019150819050949350505050565b600081519050614727816130cd565b92915050565b60006020828403121561474357614742612ec7565b5b600061475184828501614718565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614794826130c3565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036147c6576147c561475a565b5b600182019050919050565b60006147ec6147e76147e284613669565b613762565b6130c3565b9050919050565b6147fc816147d1565b82525050565b600060608201905061481760008301866147f3565b6148246020830185613822565b6148316040830184613822565b949350505050565b600082825260208201905092915050565b7f5f726567697374727920697320656d7074790000000000000000000000000000600082015250565b6000614880601283614839565b915061488b8261484a565b602082019050919050565b600060208201905081810360008301526148af81614873565b9050919050565b7f554d420000000000000000000000000000000000000000000000000000000000815250565b60006020820190506148f0600083016148b6565b919050565b7f5374616b696e6742616e6b000000000000000000000000000000000000000000815250565b600060208201905061492f600083016148f5565b919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600061496a602083614839565b915061497582614934565b602082019050919050565b600060208201905081810360008301526149998161495d565b9050919050565b60006149ab82613669565b91506149b683613669565b9250828210156149c9576149c861475a565b5b828203905092915050565b60006149df826130c3565b91506149ea836130c3565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115614a1f57614a1e61475a565b5b828201905092915050565b6000614a368285614536565b9150614a42828461467b565b6020820191508190509392505050565b614a5b816139dc565b82525050565b6000608082019050614a766000830187613099565b614a836020830186614a52565b614a906040830185613099565b614a9d6060830184613099565b95945050505050565b614aaf816132a8565b8114614aba57600080fd5b50565b600081519050614acc81614aa6565b92915050565b600060208284031215614ae857614ae7612ec7565b5b6000614af684828501614abd565b91505092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000614b5b602683614839565b9150614b6682614aff565b604082019050919050565b60006020820190508181036000830152614b8a81614b4e565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b614bc681614b91565b82525050565b6000602082019050614be16000830184614bbd565b92915050565b6000614bf38284614536565b915081905092915050565b600081519050614c0d816138c1565b92915050565b600060208284031215614c2957614c28612ec7565b5b6000614c3784828501614bfe565b91505092915050565b6000614c4b82613669565b9150614c5683613669565b92508263ffffffff03821115614c6f57614c6e61475a565b5b828201905092915050565b600080fd5b600060a08284031215614c9557614c94614c7a565b5b614c9f60a0612f4c565b90506000614caf84828501614bfe565b6000830152506020614cc384828501614bfe565b6020830152506040614cd784828501614bfe565b6040830152506060614ceb84828501614bfe565b6060830152506080614cff84828501614abd565b60808301525092915050565b600060a08284031215614d2157614d20612ec7565b5b6000614d2f84828501614c7f565b91505092915050565b6000614d43826143c1565b9150614d4e836143c1565b925082821015614d6157614d6061475a565b5b828203905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614da6826143c1565b9150614db1836143c1565b925082614dc157614dc0614d6c565b5b82820490509291505056fea2646970667358221220c360ae03d3a676b33b3c5097d3c8e8893865decc08d54266712bbb98da90469d64736f6c634300080d0033", diff --git a/deployments/eth_production/StakingBankStatic.json b/deployments/eth_production/StakingBankStatic.json index 8a9fecfe..968e3b49 100644 --- a/deployments/eth_production/StakingBankStatic.json +++ b/deployments/eth_production/StakingBankStatic.json @@ -1,5 +1,5 @@ { - "address": "0xEAFae35061473fB13d3C68F7C1dEDD8373d5E30e", + "address": "0x98b407d4961bB69615753617236118A037A67915", "abi": [ { "inputs": [ @@ -249,58 +249,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "VALIDATOR_15", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATOR_16", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATOR_17", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATOR_18", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "VALIDATOR_2", @@ -812,30 +760,30 @@ "type": "function" } ], - "transactionHash": "0x92569adb0ecaf91e81500747fb88069bd702df8f17ddc9f990eb06bfb8055f90", + "transactionHash": "0xd2f526b0a2cb9dd46d7d6356adc205cb76f2357ceaca9350f5d14295c8187c5e", "receipt": { "to": null, "from": "0xA6e4fFa19B213AbeA258ae72e8e1a209B9E543e7", - "contractAddress": "0xEAFae35061473fB13d3C68F7C1dEDD8373d5E30e", - "transactionIndex": 110, - "gasUsed": "2644122", + "contractAddress": "0x98b407d4961bB69615753617236118A037A67915", + "transactionIndex": 9, + "gasUsed": "2301671", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xa4ee514fc8da9cf7f48e2b37933b0c74e5473aa54c86cbaa24b18f5ca202742f", - "transactionHash": "0x92569adb0ecaf91e81500747fb88069bd702df8f17ddc9f990eb06bfb8055f90", + "blockHash": "0x7897fdee4d86a45b0aaabcb00074ccf2d94903e94b3b94bbd06334055c0e61b6", + "transactionHash": "0xd2f526b0a2cb9dd46d7d6356adc205cb76f2357ceaca9350f5d14295c8187c5e", "logs": [], - "blockNumber": 18519259, - "cumulativeGasUsed": "10752646", + "blockNumber": 21078133, + "cumulativeGasUsed": "3992268", "status": 1, "byzantium": true }, "args": [ - 19 + 15 ], - "numDeployments": 3, - "solcInputHash": "4db3e1d3dd51dbe508dc0a6a04352df6", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_validatorsCount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"NotSupported\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"minAmountForStake\",\"type\":\"uint256\"}],\"name\":\"LogMinAmountForStake\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"NUMBER_OF_VALIDATORS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ONE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TOTAL_SUPPLY\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_0\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_1\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_10\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_11\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_12\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_13\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_14\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_15\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_16\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_17\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_18\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_2\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_3\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_4\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_5\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_6\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_7\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_8\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_9\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_ix\",\"type\":\"uint256\"}],\"name\":\"addresses\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validator\",\"type\":\"address\"}],\"name\":\"balances\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"create\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"exit\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBalances\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"allBalances\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumberOfValidators\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"receiveApproval\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"register\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"remove\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"setMinAmountForStake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"stake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"update\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_id\",\"type\":\"address\"}],\"name\":\"validators\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"location\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_validators\",\"type\":\"address[]\"}],\"name\":\"verifyValidators\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addresses(uint256)\":{\"details\":\"gets validator address for provided index\",\"params\":{\"_ix\":\"index in array of list of all validators wallets\"}},\"balanceOf(address)\":{\"details\":\"to follow ERC20 interface\"},\"exit()\":{\"details\":\"unstake and withdraw all tokens\"},\"getName()\":{\"details\":\"to follow Registrable interface\"},\"getNumberOfValidators()\":{\"returns\":{\"_0\":\"total number of registered validators (with and without balance)\"}},\"register()\":{\"details\":\"to follow Registrable interface\"},\"totalSupply()\":{\"details\":\"to follow ERC20 interface\"},\"unregister()\":{\"details\":\"to follow Registrable interface\"},\"validators(address)\":{\"params\":{\"_id\":\"address of validator\"},\"returns\":{\"id\":\"address of validator\",\"location\":\"URL of validator\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":\"StakingBankStaticProd\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":0},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBank.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IStakingBank is IERC20 {\\n /// @param id address of validator wallet\\n /// @param location URL of the validator API\\n struct Validator {\\n address id;\\n string location;\\n }\\n\\n event LogValidatorRegistered(address indexed id);\\n event LogValidatorUpdated(address indexed id);\\n event LogValidatorRemoved(address indexed id);\\n event LogMinAmountForStake(uint256 minAmountForStake);\\n\\n /// @dev setter for `minAmountForStake`\\n function setMinAmountForStake(uint256 _minAmountForStake) external;\\n\\n /// @dev allows to stake `token` by validators\\n /// Validator needs to approve StakingBank beforehand\\n /// @param _value amount of tokens to stake\\n function stake(uint256 _value) external;\\n\\n /// @dev notification about approval from `_from` address on UMB token\\n /// Staking bank will stake max approved amount from `_from` address\\n /// @param _from address which approved token spend for IStakingBank\\n function receiveApproval(address _from) external returns (bool success);\\n\\n /// @dev withdraws stake tokens\\n /// it throws, when balance will be less than required minimum for stake\\n /// to withdraw all use `exit`\\n function withdraw(uint256 _value) external returns (bool success);\\n\\n /// @dev unstake and withdraw all tokens\\n function exit() external returns (bool success);\\n\\n /// @dev creates (register) new validator\\n /// @param _id validator address\\n /// @param _location location URL of the validator API\\n function create(address _id, string calldata _location) external;\\n\\n /// @dev removes validator\\n /// @param _id validator wallet\\n function remove(address _id) external;\\n\\n /// @dev updates validator location\\n /// @param _id validator wallet\\n /// @param _location new validator URL\\n function update(address _id, string calldata _location) external;\\n\\n /// @return total number of registered validators (with and without balance)\\n function getNumberOfValidators() external view returns (uint256);\\n\\n /// @dev gets validator address for provided index\\n /// @param _ix index in array of list of all validators wallets\\n function addresses(uint256 _ix) external view returns (address);\\n\\n /// @param _id address of validator\\n /// @return id address of validator\\n /// @return location URL of validator\\n function validators(address _id) external view returns (address id, string memory location);\\n}\\n\",\"keccak256\":\"0x2c518aeab8b0b3a364fafaec559d3ff0dc6a119f8d203fa31ef7ad667ca0f7b9\",\"license\":\"MIT\"},\"contracts/interfaces/StakingBankStaticNotSupported.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./IStakingBank.sol\\\";\\n\\nabstract contract StakingBankStaticNotSupported is IStakingBank {\\n error NotSupported();\\n\\n function create(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function update(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function remove(address) external pure {\\n revert NotSupported();\\n }\\n\\n function transfer(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function transferFrom(address, address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function receiveApproval(address) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function allowance(address, address) external pure returns (uint256) {\\n revert NotSupported();\\n }\\n\\n function approve(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function stake(uint256) external pure {\\n revert NotSupported();\\n }\\n\\n function withdraw(uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function exit() external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function setMinAmountForStake(uint256) external pure {\\n revert NotSupported();\\n }\\n}\\n\",\"keccak256\":\"0xa899ad9000220b04bc3f63f762a9a6a76dcc09449427e7774a53f4ceda9c1cf8\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStatic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"../interfaces/StakingBankStaticNotSupported.sol\\\";\\n\\n/// @dev Because we are using PoA in UMB oracle, staked balance does not matter. What's matter is, if signer is\\n/// validator or not. In this case we can optimise `StakingBank` and make it static for better gas performance.\\nabstract contract StakingBankStatic is StakingBankStaticNotSupported {\\n uint256 public constant ONE = 1e18;\\n\\n uint256 public immutable NUMBER_OF_VALIDATORS; // solhint-disable-line var-name-mixedcase\\n uint256 public immutable TOTAL_SUPPLY; // solhint-disable-line var-name-mixedcase\\n\\n constructor(uint256 _validatorsCount) {\\n NUMBER_OF_VALIDATORS = _validatorsCount;\\n TOTAL_SUPPLY = _validatorsCount * ONE;\\n\\n _assertValidSetup(_validatorsCount);\\n }\\n\\n function balances(address _validator) external view returns (uint256) {\\n return _isValidator(_validator) ? ONE : 0;\\n }\\n\\n function verifyValidators(address[] calldata _validators) external view returns (bool) {\\n for (uint256 i; i < _validators.length;) {\\n if (!_isValidator(_validators[i])) return false;\\n unchecked { i++; }\\n }\\n\\n return true;\\n }\\n\\n function getNumberOfValidators() external view returns (uint256) {\\n return NUMBER_OF_VALIDATORS;\\n }\\n\\n function getAddresses() external view returns (address[] memory) {\\n return _addresses();\\n }\\n\\n function getBalances() external view returns (uint256[] memory allBalances) {\\n allBalances = new uint256[](NUMBER_OF_VALIDATORS);\\n\\n for (uint256 i; i < NUMBER_OF_VALIDATORS;) {\\n allBalances[i] = ONE;\\n\\n unchecked {\\n // we will not have enough data to overflow\\n i++;\\n }\\n }\\n }\\n\\n function addresses(uint256 _ix) external view returns (address) {\\n return _addresses()[_ix];\\n }\\n\\n function validators(address _id) external view virtual returns (address id, string memory location);\\n\\n /// @dev to follow ERC20 interface\\n function balanceOf(address _account) external view returns (uint256) {\\n return _isValidator(_account) ? ONE : 0;\\n }\\n\\n /// @dev to follow ERC20 interface\\n function totalSupply() external view returns (uint256) {\\n return TOTAL_SUPPLY;\\n }\\n\\n /// @dev to follow Registrable interface\\n function getName() external pure returns (bytes32) {\\n return \\\"StakingBank\\\";\\n }\\n\\n /// @dev to follow Registrable interface\\n function register() external pure {\\n // there are no requirements atm\\n }\\n\\n /// @dev to follow Registrable interface\\n function unregister() external pure {\\n // there are no requirements atm\\n }\\n\\n function _addresses() internal view virtual returns (address[] memory);\\n\\n function _isValidator(address _validator) internal view virtual returns (bool);\\n\\n function _assertValidSetup(uint256 _validatorsCount) internal view virtual{\\n address[] memory list = _addresses();\\n require(list.length == _validatorsCount);\\n\\n for (uint256 i; i < _validatorsCount;) {\\n require(_isValidator(list[i]));\\n\\n unchecked { i ++; }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfcc53ff98b0f1c42e1bc7345a1535fdc4e938ef40d323600ead94b2ece59a381\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./StakingBankStatic.sol\\\";\\n\\ncontract StakingBankStaticProd is StakingBankStatic {\\n address public constant VALIDATOR_0 = 0x977Ba523420110e230643B772Fe9cF955e11dA7B;\\n address public constant VALIDATOR_1 = 0xe2422b23e52bc13ebA04d7FbB9F332Deb43360fB;\\n\\n // external order is based on validators submits on AVAX for Apr 2023\\n address public constant VALIDATOR_2 = 0x57F404aD75e371c1A539589C1eFCA12e0C6980AD;\\n address public constant VALIDATOR_3 = 0xD56C6A4f64E0bD70260472d1DB6Cf5825858CB0d;\\n address public constant VALIDATOR_4 = 0x220230Eda8f50067Dd9e4729345dabCCe0C61542;\\n address public constant VALIDATOR_5 = 0x93FdcAB283b0BcAc48157590af482E1CFd6af6aC;\\n address public constant VALIDATOR_6 = 0xCd733E06B06083d52fC5867E8E3432aA5c103A38;\\n address public constant VALIDATOR_7 = 0x42e210b110c6aa49CdfA7ceF1444Aa4719653111;\\n address public constant VALIDATOR_8 = 0x501731c6a69803a53Ec6c3e12f293c247cE1092B;\\n address public constant VALIDATOR_9 = 0x8bF9661F1b247522C75DD0FE84355aD2EfF27144;\\n address public constant VALIDATOR_10 = 0x281754Ab58391A478B7aA4E7f39991CfB41118c4;\\n address public constant VALIDATOR_11 = 0xB9C63a350A04d8BD245d18928a26EE036352dDd8;\\n address public constant VALIDATOR_12 = 0x57A51D5BDcE188c2295fCA3b4687475a54E65A02;\\n address public constant VALIDATOR_13 = 0x777FbA3666fa7747476a34577FcCC404b263E09F;\\n address public constant VALIDATOR_14 = 0x2F85824B2B38F179E451988670935d315b5b9692;\\n address public constant VALIDATOR_15 = 0xA7241994267682de4dE7Ef62f52dc2C783d1784B;\\n address public constant VALIDATOR_16 = 0x6eEd457C20603EDAE50C3A112CAA1a9425321bD0;\\n address public constant VALIDATOR_17 = 0xC5a7650c2725a7B6A39f15cb9FbffC7af357AFeb;\\n address public constant VALIDATOR_18 = 0xFEd95453678920c1b7b3A81F033Ca02a27225556;\\n\\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\\n\\n // solhint-disable-next-line code-complexity\\n function validators(address _id) external pure override returns (address id, string memory location) {\\n if (_id == VALIDATOR_0) return (_id, \\\"https://validator.umb.network\\\");\\n if (_id == VALIDATOR_1) return (_id, \\\"https://validator2.umb.network\\\");\\n if (_id == VALIDATOR_2) return (_id, \\\"https://umbrella.artemahr.tech\\\");\\n if (_id == VALIDATOR_3) return (_id, \\\"https://umb.vtabsolutions.com:3030\\\");\\n if (_id == VALIDATOR_4) return (_id, \\\"https://umb.stakers.world\\\");\\n if (_id == VALIDATOR_5) return (_id, \\\"https://umbrella.crazywhale.es\\\");\\n if (_id == VALIDATOR_6) return (_id, \\\"https://umbrella-node.gateomega.com\\\");\\n if (_id == VALIDATOR_7) return (_id, \\\"https://umb.anorak.technology\\\");\\n if (_id == VALIDATOR_8) return (_id, \\\"https://umbrella.validator.infstones.io\\\");\\n if (_id == VALIDATOR_9) return (_id, \\\"https://umb.hashquark.io\\\");\\n if (_id == VALIDATOR_10) return (_id, \\\"http://umbrella.staking4all.org:3000\\\");\\n if (_id == VALIDATOR_11) return (_id, \\\"https://umbrella-api.validatrium.club\\\");\\n if (_id == VALIDATOR_12) return (_id, \\\"http://5.161.78.230:3000\\\");\\n if (_id == VALIDATOR_13) return (_id, \\\"https://umbnode.blockchainliverpool.com\\\");\\n if (_id == VALIDATOR_14) return (_id, \\\"https://umb-api.staking.rocks\\\");\\n if (_id == VALIDATOR_15) return (_id, \\\"https://rpc.urbanhq.net\\\");\\n if (_id == VALIDATOR_16) return (_id, \\\"https://umbrella-node.ankastake.com\\\");\\n if (_id == VALIDATOR_17) return (_id, \\\"https://umbrella.tchambrella.com\\\");\\n if (_id == VALIDATOR_18) return (_id, \\\"https://umbrella-node.cmt13.eu\\\");\\n\\n return (address(0), \\\"\\\");\\n }\\n\\n function _addresses() internal view override returns (address[] memory) {\\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\\n\\n list[0] = VALIDATOR_0;\\n list[1] = VALIDATOR_1;\\n list[2] = VALIDATOR_2;\\n list[3] = VALIDATOR_3;\\n list[4] = VALIDATOR_4;\\n list[5] = VALIDATOR_5;\\n list[6] = VALIDATOR_6;\\n list[7] = VALIDATOR_7;\\n list[8] = VALIDATOR_8;\\n list[9] = VALIDATOR_9;\\n list[10] = VALIDATOR_10;\\n list[11] = VALIDATOR_11;\\n list[12] = VALIDATOR_12;\\n list[13] = VALIDATOR_13;\\n list[14] = VALIDATOR_14;\\n list[15] = VALIDATOR_15;\\n list[16] = VALIDATOR_16;\\n list[17] = VALIDATOR_17;\\n list[18] = VALIDATOR_18;\\n\\n return list;\\n }\\n\\n function _isValidator(address _validator) internal pure override returns (bool) {\\n return (\\n _validator == VALIDATOR_0\\n || _validator == VALIDATOR_1\\n || _validator == VALIDATOR_2\\n || _validator == VALIDATOR_3\\n || _validator == VALIDATOR_4\\n || _validator == VALIDATOR_5\\n || _validator == VALIDATOR_6\\n || _validator == VALIDATOR_7\\n || _validator == VALIDATOR_8\\n || _validator == VALIDATOR_9\\n || _validator == VALIDATOR_10\\n || _validator == VALIDATOR_11\\n || _validator == VALIDATOR_12\\n || _validator == VALIDATOR_13\\n || _validator == VALIDATOR_14\\n || _validator == VALIDATOR_15\\n || _validator == VALIDATOR_16\\n || _validator == VALIDATOR_17\\n || _validator == VALIDATOR_18\\n );\\n }\\n}\\n\",\"keccak256\":\"0x1e80a063f381fdb75109238bd1e4db75af37b5aea8d8165293aee4bf84838c85\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60c06040523480156200001157600080fd5b5060405162003da238038062003da2833981810160405281019062000037919062000eaf565b808060808181525050670de0b6b3a76400008162000056919062000f10565b60a081815250506200006e816200007660201b60201c565b505062000fcf565b600062000088620000ef60201b60201c565b9050818151146200009857600080fd5b60005b82811015620000ea57620000d2828281518110620000be57620000bd62000f71565b5b6020026020010151620008dd60201b60201c565b620000dc57600080fd5b80806001019150506200009b565b505050565b6060600060805167ffffffffffffffff81111562000112576200011162000fa0565b5b604051908082528060200260200182016040528015620001415781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b8160008151811062000170576200016f62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110620001d657620001d562000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad816002815181106200023c576200023b62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110620002a257620002a162000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073220230eda8f50067dd9e4729345dabcce0c615428160048151811062000308576200030762000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac816005815181106200036e576200036d62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a3881600681518110620003d457620003d362000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa4719653111816007815181106200043a576200043962000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b81600881518110620004a0576200049f62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff271448160098151811062000506576200050562000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600a815181106200056c576200056b62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073b9c63a350a04d8bd245d18928a26ee036352ddd881600b81518110620005d257620005d162000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600c8151811062000638576200063762000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073777fba3666fa7747476a34577fccc404b263e09f81600d815181106200069e576200069d62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600e8151811062000704576200070362000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600f815181106200076a576200076962000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081601081518110620007d057620007cf62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb8160118151811062000836576200083562000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073fed95453678920c1b7b3a81f033ca02a27225556816012815181106200089c576200089b62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806200096d575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80620009b857507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a03575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a4e575073220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a9957507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ae4575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b2f57507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b7a575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000bc55750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000c10575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000c5b575073b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ca657507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000cf1575073777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000d3c5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000d87575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000dd25750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000e1d575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000e68575073fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b600080fd5b6000819050919050565b62000e898162000e74565b811462000e9557600080fd5b50565b60008151905062000ea98162000e7e565b92915050565b60006020828403121562000ec85762000ec762000e6f565b5b600062000ed88482850162000e98565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600062000f1d8262000e74565b915062000f2a8362000e74565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161562000f665762000f6562000ee1565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60805160a051612d8a62001018600039600081816109ac0152610c2e01526000818161081b0152818161088901528181610c5401528181610dbd0152611db40152612d8a6000f3fe608060405234801561001057600080fd5b50600436106102195760003560e01c8062113e081461021e578063015f7ed61461023c57806303a1e2241461025a578063095ea7b3146102785780630db18e37146102a857806317d7de7c146102d857806318160ddd146102f65780631aa3a008146103145780631d4f9ce01461031e57806323b872dd1461034e57806327e235e31461037e57806329092d0e146103ae5780632e1a7d4d146103ca578063398b056e146103fa578063411ff4971461041857806345f9f8251461043657806352b41e351461045457806354755335146104705780635dc4bfd31461048e57806361a3e37e146104ac57806369dc7ae4146104ca57806370a08231146104e8578063838e7c3a14610518578063902d55a5146105345780639031d9131461055257806390ff7e2e14610570578063952c4f181461058e578063989b6996146105ac5780639f0e9484146105ca578063a15ab08d146105e8578063a39fac1214610604578063a694fc3a14610622578063a9059cbb1461063e578063b2119eac1461066e578063b49b08421461068c578063c2ee3a08146106aa578063db731777146106c8578063dd62ed3e146106e6578063e214a5fc14610716578063e29349d614610734578063e2dc7a1a14610752578063e79a198f14610770578063e985e0081461077a578063e9fad8ee14610798578063edf26d9b146107b6578063fa52c7d8146107e6575b600080fd5b610226610817565b6040516102339190612645565b60405180910390f35b6102446108e8565b60405161025191906126a8565b60405180910390f35b610262610900565b60405161026f91906126a8565b60405180910390f35b610292600480360381019061028d9190612725565b610918565b60405161029f9190612780565b60405180910390f35b6102c260048036038101906102bd919061279b565b61094c565b6040516102cf9190612780565b60405180910390f35b6102e0610980565b6040516102ed91906127e1565b60405180910390f35b6102fe6109a8565b60405161030b919061280b565b60405180910390f35b61031c6109d0565b005b6103386004803603810190610333919061288b565b6109d2565b6040516103459190612780565b60405180910390f35b610368600480360381019061036391906128d8565b610a38565b6040516103759190612780565b60405180910390f35b6103986004803603810190610393919061279b565b610a6c565b6040516103a5919061280b565b60405180910390f35b6103c860048036038101906103c3919061279b565b610a93565b005b6103e460048036038101906103df919061292b565b610ac5565b6040516103f19190612780565b60405180910390f35b610402610af9565b60405161040f91906126a8565b60405180910390f35b610420610b11565b60405161042d91906126a8565b60405180910390f35b61043e610b29565b60405161044b91906126a8565b60405180910390f35b61046e6004803603810190610469919061292b565b610b41565b005b610478610b73565b60405161048591906126a8565b60405180910390f35b610496610b8b565b6040516104a391906126a8565b60405180910390f35b6104b4610ba3565b6040516104c191906126a8565b60405180910390f35b6104d2610bbb565b6040516104df91906126a8565b60405180910390f35b61050260048036038101906104fd919061279b565b610bd3565b60405161050f919061280b565b60405180910390f35b610532600480360381019061052d91906129ae565b610bfa565b005b61053c610c2c565b604051610549919061280b565b60405180910390f35b61055a610c50565b604051610567919061280b565b60405180910390f35b610578610c78565b60405161058591906126a8565b60405180910390f35b610596610c90565b6040516105a391906126a8565b60405180910390f35b6105b4610ca8565b6040516105c191906126a8565b60405180910390f35b6105d2610cc0565b6040516105df91906126a8565b60405180910390f35b61060260048036038101906105fd91906129ae565b610cd8565b005b61060c610d0a565b6040516106199190612acc565b60405180910390f35b61063c6004803603810190610637919061292b565b610d19565b005b61065860048036038101906106539190612725565b610d4b565b6040516106659190612780565b60405180910390f35b610676610d7f565b60405161068391906126a8565b60405180910390f35b610694610d97565b6040516106a191906126a8565b60405180910390f35b6106b2610daf565b6040516106bf919061280b565b60405180910390f35b6106d0610dbb565b6040516106dd919061280b565b60405180910390f35b61070060048036038101906106fb9190612aee565b610ddf565b60405161070d919061280b565b60405180910390f35b61071e610e13565b60405161072b91906126a8565b60405180910390f35b61073c610e2b565b60405161074991906126a8565b60405180910390f35b61075a610e43565b60405161076791906126a8565b60405180910390f35b610778610e5b565b005b610782610e5d565b60405161078f91906126a8565b60405180910390f35b6107a0610e75565b6040516107ad9190612780565b60405180910390f35b6107d060048036038101906107cb919061292b565b610ea9565b6040516107dd91906126a8565b60405180910390f35b61080060048036038101906107fb919061279b565b610ed4565b60405161080e929190612bc7565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff81111561085357610852612bf7565b5b6040519080825280602002602001820160405280156108815781602001602082028036833780820191505090505b50905060005b7f00000000000000000000000000000000000000000000000000000000000000008110156108e457670de0b6b3a76400008282815181106108cb576108ca612c26565b5b6020026020010181815250508080600101915050610887565b5090565b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b83839050811015610a2c57610a118484838181106109f7576109f6612c26565b5b9050602002016020810190610a0c919061279b565b61182e565b610a1f576000915050610a32565b80806001019150506109d6565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a778261182e565b610a82576000610a8c565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b732f85824b2b38f179e451988670935d315b5b969281565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b73fed95453678920c1b7b3a81f033ca02a2722555681565b73777fba3666fa7747476a34577fccc404b263e09f81565b6000610bde8261182e565b610be9576000610bf3565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b73220230eda8f50067dd9e4729345dabcce0c6154281565b73a7241994267682de4de7ef62f52dc2c783d1784b81565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610d14611dae565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73281754ab58391a478b7aa4e7f39991cfb41118c481565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b736eed457c20603edae50c3a112caa1a9425321bd081565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b565b73b9c63a350a04d8bd245d18928a26ee036352ddd881565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610eb3611dae565b8281518110610ec557610ec4612c26565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f5f57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611829565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fe657826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611829565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361106d57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611829565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110d75782604051806060016040528060228152602001612c796022913991509150611829565b73220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361115e57826040518060400160405280601981526020017f68747470733a2f2f756d622e7374616b6572732e776f726c640000000000000081525091509150611829565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111e557826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611829565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361124f5782604051806060016040528060238152602001612c566023913991509150611829565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112d657826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611829565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113405782604051806060016040528060278152602001612cbf6027913991509150611829565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113c757826040518060400160405280601881526020017f68747470733a2f2f756d622e68617368717561726b2e696f000000000000000081525091509150611829565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114315782604051806060016040528060248152602001612c9b6024913991509150611829565b73b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361149b5782604051806060016040528060258152602001612ce66025913991509150611829565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152257826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611829565b73777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361158c5782604051806060016040528060278152602001612d2e6027913991509150611829565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361161357826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611829565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361169a57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611829565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036117045782604051806060016040528060238152602001612d0b6023913991509150611829565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361178b57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611829565b73fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361181257826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612d6e6f64652e636d7431332e6575000081525091509150611829565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806118bd575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061190757507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611951575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061199b575073220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806119e557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a2f575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a7957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ac3575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b0d5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b57575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ba1575073b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611beb57507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c35575073777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c7f5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611cc9575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d135750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d5d575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611da7575073fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff811115611dec57611deb612bf7565b5b604051908082528060200260200182016040528015611e1a5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611e4657611e45612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611ea957611ea8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611f0c57611f0b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611f6f57611f6e612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073220230eda8f50067dd9e4729345dabcce0c6154281600481518110611fd257611fd1612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac8160058151811061203557612034612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a388160068151811061209857612097612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa4719653111816007815181106120fb576120fa612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b8160088151811061215e5761215d612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff27144816009815181106121c1576121c0612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600a8151811061222457612223612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073b9c63a350a04d8bd245d18928a26ee036352ddd881600b8151811061228757612286612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600c815181106122ea576122e9612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073777fba3666fa7747476a34577fccc404b263e09f81600d8151811061234d5761234c612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600e815181106123b0576123af612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600f8151811061241357612412612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd08160108151811061247657612475612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb816011815181106124d9576124d8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073fed95453678920c1b7b3a81f033ca02a272255568160128151811061253c5761253b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6125bc816125a9565b82525050565b60006125ce83836125b3565b60208301905092915050565b6000602082019050919050565b60006125f28261257d565b6125fc8185612588565b935061260783612599565b8060005b8381101561263857815161261f88826125c2565b975061262a836125da565b92505060018101905061260b565b5085935050505092915050565b6000602082019050818103600083015261265f81846125e7565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061269282612667565b9050919050565b6126a281612687565b82525050565b60006020820190506126bd6000830184612699565b92915050565b600080fd5b600080fd5b6126d681612687565b81146126e157600080fd5b50565b6000813590506126f3816126cd565b92915050565b612702816125a9565b811461270d57600080fd5b50565b60008135905061271f816126f9565b92915050565b6000806040838503121561273c5761273b6126c3565b5b600061274a858286016126e4565b925050602061275b85828601612710565b9150509250929050565b60008115159050919050565b61277a81612765565b82525050565b60006020820190506127956000830184612771565b92915050565b6000602082840312156127b1576127b06126c3565b5b60006127bf848285016126e4565b91505092915050565b6000819050919050565b6127db816127c8565b82525050565b60006020820190506127f660008301846127d2565b92915050565b612805816125a9565b82525050565b600060208201905061282060008301846127fc565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261284b5761284a612826565b5b8235905067ffffffffffffffff8111156128685761286761282b565b5b60208301915083602082028301111561288457612883612830565b5b9250929050565b600080602083850312156128a2576128a16126c3565b5b600083013567ffffffffffffffff8111156128c0576128bf6126c8565b5b6128cc85828601612835565b92509250509250929050565b6000806000606084860312156128f1576128f06126c3565b5b60006128ff868287016126e4565b9350506020612910868287016126e4565b925050604061292186828701612710565b9150509250925092565b600060208284031215612941576129406126c3565b5b600061294f84828501612710565b91505092915050565b60008083601f84011261296e5761296d612826565b5b8235905067ffffffffffffffff81111561298b5761298a61282b565b5b6020830191508360018202830111156129a7576129a6612830565b5b9250929050565b6000806000604084860312156129c7576129c66126c3565b5b60006129d5868287016126e4565b935050602084013567ffffffffffffffff8111156129f6576129f56126c8565b5b612a0286828701612958565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b612a4381612687565b82525050565b6000612a558383612a3a565b60208301905092915050565b6000602082019050919050565b6000612a7982612a0e565b612a838185612a19565b9350612a8e83612a2a565b8060005b83811015612abf578151612aa68882612a49565b9750612ab183612a61565b925050600181019050612a92565b5085935050505092915050565b60006020820190508181036000830152612ae68184612a6e565b905092915050565b60008060408385031215612b0557612b046126c3565b5b6000612b13858286016126e4565b9250506020612b24858286016126e4565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612b68578082015181840152602081019050612b4d565b83811115612b77576000848401525b50505050565b6000601f19601f8301169050919050565b6000612b9982612b2e565b612ba38185612b39565b9350612bb3818560208601612b4a565b612bbc81612b7d565b840191505092915050565b6000604082019050612bdc6000830185612699565b8181036020830152612bee8184612b8e565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6170692e76616c696461747269756d2e636c756268747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6d68747470733a2f2f756d626e6f64652e626c6f636b636861696e6c69766572706f6f6c2e636f6da26469706673582212209a1752a9ea487818b8a4d658f151da9487c0cc92638142159bacde7ec2d21f7564736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102195760003560e01c8062113e081461021e578063015f7ed61461023c57806303a1e2241461025a578063095ea7b3146102785780630db18e37146102a857806317d7de7c146102d857806318160ddd146102f65780631aa3a008146103145780631d4f9ce01461031e57806323b872dd1461034e57806327e235e31461037e57806329092d0e146103ae5780632e1a7d4d146103ca578063398b056e146103fa578063411ff4971461041857806345f9f8251461043657806352b41e351461045457806354755335146104705780635dc4bfd31461048e57806361a3e37e146104ac57806369dc7ae4146104ca57806370a08231146104e8578063838e7c3a14610518578063902d55a5146105345780639031d9131461055257806390ff7e2e14610570578063952c4f181461058e578063989b6996146105ac5780639f0e9484146105ca578063a15ab08d146105e8578063a39fac1214610604578063a694fc3a14610622578063a9059cbb1461063e578063b2119eac1461066e578063b49b08421461068c578063c2ee3a08146106aa578063db731777146106c8578063dd62ed3e146106e6578063e214a5fc14610716578063e29349d614610734578063e2dc7a1a14610752578063e79a198f14610770578063e985e0081461077a578063e9fad8ee14610798578063edf26d9b146107b6578063fa52c7d8146107e6575b600080fd5b610226610817565b6040516102339190612645565b60405180910390f35b6102446108e8565b60405161025191906126a8565b60405180910390f35b610262610900565b60405161026f91906126a8565b60405180910390f35b610292600480360381019061028d9190612725565b610918565b60405161029f9190612780565b60405180910390f35b6102c260048036038101906102bd919061279b565b61094c565b6040516102cf9190612780565b60405180910390f35b6102e0610980565b6040516102ed91906127e1565b60405180910390f35b6102fe6109a8565b60405161030b919061280b565b60405180910390f35b61031c6109d0565b005b6103386004803603810190610333919061288b565b6109d2565b6040516103459190612780565b60405180910390f35b610368600480360381019061036391906128d8565b610a38565b6040516103759190612780565b60405180910390f35b6103986004803603810190610393919061279b565b610a6c565b6040516103a5919061280b565b60405180910390f35b6103c860048036038101906103c3919061279b565b610a93565b005b6103e460048036038101906103df919061292b565b610ac5565b6040516103f19190612780565b60405180910390f35b610402610af9565b60405161040f91906126a8565b60405180910390f35b610420610b11565b60405161042d91906126a8565b60405180910390f35b61043e610b29565b60405161044b91906126a8565b60405180910390f35b61046e6004803603810190610469919061292b565b610b41565b005b610478610b73565b60405161048591906126a8565b60405180910390f35b610496610b8b565b6040516104a391906126a8565b60405180910390f35b6104b4610ba3565b6040516104c191906126a8565b60405180910390f35b6104d2610bbb565b6040516104df91906126a8565b60405180910390f35b61050260048036038101906104fd919061279b565b610bd3565b60405161050f919061280b565b60405180910390f35b610532600480360381019061052d91906129ae565b610bfa565b005b61053c610c2c565b604051610549919061280b565b60405180910390f35b61055a610c50565b604051610567919061280b565b60405180910390f35b610578610c78565b60405161058591906126a8565b60405180910390f35b610596610c90565b6040516105a391906126a8565b60405180910390f35b6105b4610ca8565b6040516105c191906126a8565b60405180910390f35b6105d2610cc0565b6040516105df91906126a8565b60405180910390f35b61060260048036038101906105fd91906129ae565b610cd8565b005b61060c610d0a565b6040516106199190612acc565b60405180910390f35b61063c6004803603810190610637919061292b565b610d19565b005b61065860048036038101906106539190612725565b610d4b565b6040516106659190612780565b60405180910390f35b610676610d7f565b60405161068391906126a8565b60405180910390f35b610694610d97565b6040516106a191906126a8565b60405180910390f35b6106b2610daf565b6040516106bf919061280b565b60405180910390f35b6106d0610dbb565b6040516106dd919061280b565b60405180910390f35b61070060048036038101906106fb9190612aee565b610ddf565b60405161070d919061280b565b60405180910390f35b61071e610e13565b60405161072b91906126a8565b60405180910390f35b61073c610e2b565b60405161074991906126a8565b60405180910390f35b61075a610e43565b60405161076791906126a8565b60405180910390f35b610778610e5b565b005b610782610e5d565b60405161078f91906126a8565b60405180910390f35b6107a0610e75565b6040516107ad9190612780565b60405180910390f35b6107d060048036038101906107cb919061292b565b610ea9565b6040516107dd91906126a8565b60405180910390f35b61080060048036038101906107fb919061279b565b610ed4565b60405161080e929190612bc7565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff81111561085357610852612bf7565b5b6040519080825280602002602001820160405280156108815781602001602082028036833780820191505090505b50905060005b7f00000000000000000000000000000000000000000000000000000000000000008110156108e457670de0b6b3a76400008282815181106108cb576108ca612c26565b5b6020026020010181815250508080600101915050610887565b5090565b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b83839050811015610a2c57610a118484838181106109f7576109f6612c26565b5b9050602002016020810190610a0c919061279b565b61182e565b610a1f576000915050610a32565b80806001019150506109d6565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a778261182e565b610a82576000610a8c565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b732f85824b2b38f179e451988670935d315b5b969281565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b73fed95453678920c1b7b3a81f033ca02a2722555681565b73777fba3666fa7747476a34577fccc404b263e09f81565b6000610bde8261182e565b610be9576000610bf3565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b73220230eda8f50067dd9e4729345dabcce0c6154281565b73a7241994267682de4de7ef62f52dc2c783d1784b81565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610d14611dae565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73281754ab58391a478b7aa4e7f39991cfb41118c481565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b736eed457c20603edae50c3a112caa1a9425321bd081565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b565b73b9c63a350a04d8bd245d18928a26ee036352ddd881565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610eb3611dae565b8281518110610ec557610ec4612c26565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f5f57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611829565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fe657826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611829565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361106d57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611829565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110d75782604051806060016040528060228152602001612c796022913991509150611829565b73220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361115e57826040518060400160405280601981526020017f68747470733a2f2f756d622e7374616b6572732e776f726c640000000000000081525091509150611829565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111e557826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611829565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361124f5782604051806060016040528060238152602001612c566023913991509150611829565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112d657826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611829565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113405782604051806060016040528060278152602001612cbf6027913991509150611829565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113c757826040518060400160405280601881526020017f68747470733a2f2f756d622e68617368717561726b2e696f000000000000000081525091509150611829565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114315782604051806060016040528060248152602001612c9b6024913991509150611829565b73b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361149b5782604051806060016040528060258152602001612ce66025913991509150611829565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152257826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611829565b73777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361158c5782604051806060016040528060278152602001612d2e6027913991509150611829565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361161357826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611829565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361169a57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611829565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036117045782604051806060016040528060238152602001612d0b6023913991509150611829565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361178b57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611829565b73fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361181257826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612d6e6f64652e636d7431332e6575000081525091509150611829565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806118bd575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061190757507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611951575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061199b575073220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806119e557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a2f575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a7957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ac3575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b0d5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b57575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ba1575073b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611beb57507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c35575073777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c7f5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611cc9575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d135750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d5d575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611da7575073fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff811115611dec57611deb612bf7565b5b604051908082528060200260200182016040528015611e1a5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611e4657611e45612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611ea957611ea8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611f0c57611f0b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611f6f57611f6e612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073220230eda8f50067dd9e4729345dabcce0c6154281600481518110611fd257611fd1612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac8160058151811061203557612034612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a388160068151811061209857612097612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa4719653111816007815181106120fb576120fa612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b8160088151811061215e5761215d612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff27144816009815181106121c1576121c0612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600a8151811061222457612223612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073b9c63a350a04d8bd245d18928a26ee036352ddd881600b8151811061228757612286612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600c815181106122ea576122e9612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073777fba3666fa7747476a34577fccc404b263e09f81600d8151811061234d5761234c612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600e815181106123b0576123af612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600f8151811061241357612412612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd08160108151811061247657612475612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb816011815181106124d9576124d8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073fed95453678920c1b7b3a81f033ca02a272255568160128151811061253c5761253b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6125bc816125a9565b82525050565b60006125ce83836125b3565b60208301905092915050565b6000602082019050919050565b60006125f28261257d565b6125fc8185612588565b935061260783612599565b8060005b8381101561263857815161261f88826125c2565b975061262a836125da565b92505060018101905061260b565b5085935050505092915050565b6000602082019050818103600083015261265f81846125e7565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061269282612667565b9050919050565b6126a281612687565b82525050565b60006020820190506126bd6000830184612699565b92915050565b600080fd5b600080fd5b6126d681612687565b81146126e157600080fd5b50565b6000813590506126f3816126cd565b92915050565b612702816125a9565b811461270d57600080fd5b50565b60008135905061271f816126f9565b92915050565b6000806040838503121561273c5761273b6126c3565b5b600061274a858286016126e4565b925050602061275b85828601612710565b9150509250929050565b60008115159050919050565b61277a81612765565b82525050565b60006020820190506127956000830184612771565b92915050565b6000602082840312156127b1576127b06126c3565b5b60006127bf848285016126e4565b91505092915050565b6000819050919050565b6127db816127c8565b82525050565b60006020820190506127f660008301846127d2565b92915050565b612805816125a9565b82525050565b600060208201905061282060008301846127fc565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261284b5761284a612826565b5b8235905067ffffffffffffffff8111156128685761286761282b565b5b60208301915083602082028301111561288457612883612830565b5b9250929050565b600080602083850312156128a2576128a16126c3565b5b600083013567ffffffffffffffff8111156128c0576128bf6126c8565b5b6128cc85828601612835565b92509250509250929050565b6000806000606084860312156128f1576128f06126c3565b5b60006128ff868287016126e4565b9350506020612910868287016126e4565b925050604061292186828701612710565b9150509250925092565b600060208284031215612941576129406126c3565b5b600061294f84828501612710565b91505092915050565b60008083601f84011261296e5761296d612826565b5b8235905067ffffffffffffffff81111561298b5761298a61282b565b5b6020830191508360018202830111156129a7576129a6612830565b5b9250929050565b6000806000604084860312156129c7576129c66126c3565b5b60006129d5868287016126e4565b935050602084013567ffffffffffffffff8111156129f6576129f56126c8565b5b612a0286828701612958565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b612a4381612687565b82525050565b6000612a558383612a3a565b60208301905092915050565b6000602082019050919050565b6000612a7982612a0e565b612a838185612a19565b9350612a8e83612a2a565b8060005b83811015612abf578151612aa68882612a49565b9750612ab183612a61565b925050600181019050612a92565b5085935050505092915050565b60006020820190508181036000830152612ae68184612a6e565b905092915050565b60008060408385031215612b0557612b046126c3565b5b6000612b13858286016126e4565b9250506020612b24858286016126e4565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612b68578082015181840152602081019050612b4d565b83811115612b77576000848401525b50505050565b6000601f19601f8301169050919050565b6000612b9982612b2e565b612ba38185612b39565b9350612bb3818560208601612b4a565b612bbc81612b7d565b840191505092915050565b6000604082019050612bdc6000830185612699565b8181036020830152612bee8184612b8e565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6170692e76616c696461747269756d2e636c756268747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6d68747470733a2f2f756d626e6f64652e626c6f636b636861696e6c69766572706f6f6c2e636f6da26469706673582212209a1752a9ea487818b8a4d658f151da9487c0cc92638142159bacde7ec2d21f7564736f6c634300080d0033", + "numDeployments": 4, + "solcInputHash": "dc68422c0ad35a4fe46d461b096b9383", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_validatorsCount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"NotSupported\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"minAmountForStake\",\"type\":\"uint256\"}],\"name\":\"LogMinAmountForStake\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"NUMBER_OF_VALIDATORS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ONE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TOTAL_SUPPLY\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_0\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_1\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_10\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_11\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_12\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_13\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_14\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_2\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_3\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_4\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_5\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_6\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_7\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_8\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_9\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_ix\",\"type\":\"uint256\"}],\"name\":\"addresses\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validator\",\"type\":\"address\"}],\"name\":\"balances\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"create\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"exit\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBalances\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"allBalances\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumberOfValidators\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"receiveApproval\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"register\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"remove\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"setMinAmountForStake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"stake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"update\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_id\",\"type\":\"address\"}],\"name\":\"validators\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"location\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_validators\",\"type\":\"address[]\"}],\"name\":\"verifyValidators\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addresses(uint256)\":{\"details\":\"gets validator address for provided index\",\"params\":{\"_ix\":\"index in array of list of all validators wallets\"}},\"balanceOf(address)\":{\"details\":\"to follow ERC20 interface\"},\"exit()\":{\"details\":\"unstake and withdraw all tokens\"},\"getName()\":{\"details\":\"to follow Registrable interface\"},\"getNumberOfValidators()\":{\"returns\":{\"_0\":\"total number of registered validators (with and without balance)\"}},\"register()\":{\"details\":\"to follow Registrable interface\"},\"totalSupply()\":{\"details\":\"to follow ERC20 interface\"},\"unregister()\":{\"details\":\"to follow Registrable interface\"},\"validators(address)\":{\"params\":{\"_id\":\"address of validator\"},\"returns\":{\"id\":\"address of validator\",\"location\":\"URL of validator\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":\"StakingBankStaticProd\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":0},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBank.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IStakingBank is IERC20 {\\n /// @param id address of validator wallet\\n /// @param location URL of the validator API\\n struct Validator {\\n address id;\\n string location;\\n }\\n\\n event LogValidatorRegistered(address indexed id);\\n event LogValidatorUpdated(address indexed id);\\n event LogValidatorRemoved(address indexed id);\\n event LogMinAmountForStake(uint256 minAmountForStake);\\n\\n /// @dev setter for `minAmountForStake`\\n function setMinAmountForStake(uint256 _minAmountForStake) external;\\n\\n /// @dev allows to stake `token` by validators\\n /// Validator needs to approve StakingBank beforehand\\n /// @param _value amount of tokens to stake\\n function stake(uint256 _value) external;\\n\\n /// @dev notification about approval from `_from` address on UMB token\\n /// Staking bank will stake max approved amount from `_from` address\\n /// @param _from address which approved token spend for IStakingBank\\n function receiveApproval(address _from) external returns (bool success);\\n\\n /// @dev withdraws stake tokens\\n /// it throws, when balance will be less than required minimum for stake\\n /// to withdraw all use `exit`\\n function withdraw(uint256 _value) external returns (bool success);\\n\\n /// @dev unstake and withdraw all tokens\\n function exit() external returns (bool success);\\n\\n /// @dev creates (register) new validator\\n /// @param _id validator address\\n /// @param _location location URL of the validator API\\n function create(address _id, string calldata _location) external;\\n\\n /// @dev removes validator\\n /// @param _id validator wallet\\n function remove(address _id) external;\\n\\n /// @dev updates validator location\\n /// @param _id validator wallet\\n /// @param _location new validator URL\\n function update(address _id, string calldata _location) external;\\n\\n /// @return total number of registered validators (with and without balance)\\n function getNumberOfValidators() external view returns (uint256);\\n\\n /// @dev gets validator address for provided index\\n /// @param _ix index in array of list of all validators wallets\\n function addresses(uint256 _ix) external view returns (address);\\n\\n /// @param _id address of validator\\n /// @return id address of validator\\n /// @return location URL of validator\\n function validators(address _id) external view returns (address id, string memory location);\\n}\\n\",\"keccak256\":\"0x2c518aeab8b0b3a364fafaec559d3ff0dc6a119f8d203fa31ef7ad667ca0f7b9\",\"license\":\"MIT\"},\"contracts/interfaces/StakingBankStaticNotSupported.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./IStakingBank.sol\\\";\\n\\nabstract contract StakingBankStaticNotSupported is IStakingBank {\\n error NotSupported();\\n\\n function create(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function update(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function remove(address) external pure {\\n revert NotSupported();\\n }\\n\\n function transfer(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function transferFrom(address, address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function receiveApproval(address) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function allowance(address, address) external pure returns (uint256) {\\n revert NotSupported();\\n }\\n\\n function approve(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function stake(uint256) external pure {\\n revert NotSupported();\\n }\\n\\n function withdraw(uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function exit() external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function setMinAmountForStake(uint256) external pure {\\n revert NotSupported();\\n }\\n}\\n\",\"keccak256\":\"0xa899ad9000220b04bc3f63f762a9a6a76dcc09449427e7774a53f4ceda9c1cf8\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStatic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"../interfaces/StakingBankStaticNotSupported.sol\\\";\\n\\n/// @dev Because we are using PoA in UMB oracle, staked balance does not matter. What's matter is, if signer is\\n/// validator or not. In this case we can optimise `StakingBank` and make it static for better gas performance.\\nabstract contract StakingBankStatic is StakingBankStaticNotSupported {\\n uint256 public constant ONE = 1e18;\\n\\n uint256 public immutable NUMBER_OF_VALIDATORS; // solhint-disable-line var-name-mixedcase\\n uint256 public immutable TOTAL_SUPPLY; // solhint-disable-line var-name-mixedcase\\n\\n constructor(uint256 _validatorsCount) {\\n NUMBER_OF_VALIDATORS = _validatorsCount;\\n TOTAL_SUPPLY = _validatorsCount * ONE;\\n\\n _assertValidSetup(_validatorsCount);\\n }\\n\\n function balances(address _validator) external view returns (uint256) {\\n return _isValidator(_validator) ? ONE : 0;\\n }\\n\\n function verifyValidators(address[] calldata _validators) external view returns (bool) {\\n for (uint256 i; i < _validators.length;) {\\n if (!_isValidator(_validators[i])) return false;\\n unchecked { i++; }\\n }\\n\\n return true;\\n }\\n\\n function getNumberOfValidators() external view returns (uint256) {\\n return NUMBER_OF_VALIDATORS;\\n }\\n\\n function getAddresses() external view returns (address[] memory) {\\n return _addresses();\\n }\\n\\n function getBalances() external view returns (uint256[] memory allBalances) {\\n allBalances = new uint256[](NUMBER_OF_VALIDATORS);\\n\\n for (uint256 i; i < NUMBER_OF_VALIDATORS;) {\\n allBalances[i] = ONE;\\n\\n unchecked {\\n // we will not have enough data to overflow\\n i++;\\n }\\n }\\n }\\n\\n function addresses(uint256 _ix) external view returns (address) {\\n return _addresses()[_ix];\\n }\\n\\n function validators(address _id) external view virtual returns (address id, string memory location);\\n\\n /// @dev to follow ERC20 interface\\n function balanceOf(address _account) external view returns (uint256) {\\n return _isValidator(_account) ? ONE : 0;\\n }\\n\\n /// @dev to follow ERC20 interface\\n function totalSupply() external view returns (uint256) {\\n return TOTAL_SUPPLY;\\n }\\n\\n /// @dev to follow Registrable interface\\n function getName() external pure returns (bytes32) {\\n return \\\"StakingBank\\\";\\n }\\n\\n /// @dev to follow Registrable interface\\n function register() external pure {\\n // there are no requirements atm\\n }\\n\\n /// @dev to follow Registrable interface\\n function unregister() external pure {\\n // there are no requirements atm\\n }\\n\\n function _addresses() internal view virtual returns (address[] memory);\\n\\n function _isValidator(address _validator) internal view virtual returns (bool);\\n\\n function _assertValidSetup(uint256 _validatorsCount) internal view virtual{\\n address[] memory list = _addresses();\\n require(list.length == _validatorsCount);\\n\\n for (uint256 i; i < _validatorsCount;) {\\n require(_isValidator(list[i]));\\n\\n unchecked { i ++; }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfcc53ff98b0f1c42e1bc7345a1535fdc4e938ef40d323600ead94b2ece59a381\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./StakingBankStatic.sol\\\";\\n\\ncontract StakingBankStaticProd is StakingBankStatic {\\n address public constant VALIDATOR_0 = 0x977Ba523420110e230643B772Fe9cF955e11dA7B;\\n address public constant VALIDATOR_1 = 0xe2422b23e52bc13ebA04d7FbB9F332Deb43360fB;\\n\\n // external order is based on validators submits on AVAX for Apr 2023\\n address public constant VALIDATOR_2 = 0x57F404aD75e371c1A539589C1eFCA12e0C6980AD;\\n address public constant VALIDATOR_3 = 0xD56C6A4f64E0bD70260472d1DB6Cf5825858CB0d;\\n address public constant VALIDATOR_4 = 0x93FdcAB283b0BcAc48157590af482E1CFd6af6aC;\\n address public constant VALIDATOR_5 = 0xCd733E06B06083d52fC5867E8E3432aA5c103A38;\\n address public constant VALIDATOR_6 = 0x42e210b110c6aa49CdfA7ceF1444Aa4719653111;\\n address public constant VALIDATOR_7 = 0x501731c6a69803a53Ec6c3e12f293c247cE1092B;\\n address public constant VALIDATOR_8 = 0x8bF9661F1b247522C75DD0FE84355aD2EfF27144;\\n address public constant VALIDATOR_9 = 0x281754Ab58391A478B7aA4E7f39991CfB41118c4;\\n address public constant VALIDATOR_10 = 0x57A51D5BDcE188c2295fCA3b4687475a54E65A02;\\n address public constant VALIDATOR_11 = 0x2F85824B2B38F179E451988670935d315b5b9692;\\n address public constant VALIDATOR_12 = 0xA7241994267682de4dE7Ef62f52dc2C783d1784B;\\n address public constant VALIDATOR_13 = 0x6eEd457C20603EDAE50C3A112CAA1a9425321bD0;\\n address public constant VALIDATOR_14 = 0xC5a7650c2725a7B6A39f15cb9FbffC7af357AFeb;\\n\\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\\n\\n // solhint-disable-next-line code-complexity\\n function validators(address _id) external pure override returns (address id, string memory location) {\\n if (_id == VALIDATOR_0) return (_id, \\\"https://validator.umb.network\\\");\\n if (_id == VALIDATOR_1) return (_id, \\\"https://validator2.umb.network\\\");\\n if (_id == VALIDATOR_2) return (_id, \\\"https://umbrella.artemahr.tech\\\");\\n if (_id == VALIDATOR_3) return (_id, \\\"https://umb.vtabsolutions.com:3030\\\");\\n if (_id == VALIDATOR_4) return (_id, \\\"https://umbrella.crazywhale.es\\\");\\n if (_id == VALIDATOR_5) return (_id, \\\"https://umbrella-node.gateomega.com\\\");\\n if (_id == VALIDATOR_6) return (_id, \\\"https://umb.anorak.technology\\\");\\n if (_id == VALIDATOR_7) return (_id, \\\"https://umbrella.validator.infstones.io\\\");\\n if (_id == VALIDATOR_8) return (_id, \\\"https://umb.hashkey.cloud\\\");\\n if (_id == VALIDATOR_9) return (_id, \\\"http://umbrella.staking4all.org:3000\\\");\\n if (_id == VALIDATOR_10) return (_id, \\\"http://5.161.78.230:3000\\\");\\n if (_id == VALIDATOR_11) return (_id, \\\"https://umb-api.staking.rocks\\\");\\n if (_id == VALIDATOR_12) return (_id, \\\"https://rpc.urbanhq.net\\\");\\n if (_id == VALIDATOR_13) return (_id, \\\"https://umbrella-node.ankastake.com\\\");\\n if (_id == VALIDATOR_14) return (_id, \\\"https://umbrella.tchambrella.com\\\");\\n\\n return (address(0), \\\"\\\");\\n }\\n\\n function _addresses() internal view override returns (address[] memory) {\\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\\n\\n list[0] = VALIDATOR_0;\\n list[1] = VALIDATOR_1;\\n list[2] = VALIDATOR_2;\\n list[3] = VALIDATOR_3;\\n list[4] = VALIDATOR_4;\\n list[5] = VALIDATOR_5;\\n list[6] = VALIDATOR_6;\\n list[7] = VALIDATOR_7;\\n list[8] = VALIDATOR_8;\\n list[9] = VALIDATOR_9;\\n list[10] = VALIDATOR_10;\\n list[11] = VALIDATOR_11;\\n list[12] = VALIDATOR_12;\\n list[13] = VALIDATOR_13;\\n list[14] = VALIDATOR_14;\\n\\n return list;\\n }\\n\\n function _isValidator(address _validator) internal pure override returns (bool) {\\n return (\\n _validator == VALIDATOR_0\\n || _validator == VALIDATOR_1\\n || _validator == VALIDATOR_2\\n || _validator == VALIDATOR_3\\n || _validator == VALIDATOR_4\\n || _validator == VALIDATOR_5\\n || _validator == VALIDATOR_6\\n || _validator == VALIDATOR_7\\n || _validator == VALIDATOR_8\\n || _validator == VALIDATOR_9\\n || _validator == VALIDATOR_10\\n || _validator == VALIDATOR_11\\n || _validator == VALIDATOR_12\\n || _validator == VALIDATOR_13\\n || _validator == VALIDATOR_14\\n );\\n }\\n}\\n\",\"keccak256\":\"0xcf8016c7d7325800fb6ac9f7afd34804b738daded6239139b23f894855a4f98b\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c06040523480156200001157600080fd5b50604051620034f8380380620034f8833981810160405281019062000037919062000beb565b808060808181525050670de0b6b3a76400008162000056919062000c4c565b60a081815250506200006e816200007660201b60201c565b505062000d0b565b600062000088620000ef60201b60201c565b9050818151146200009857600080fd5b60005b82811015620000ea57620000d2828281518110620000be57620000bd62000cad565b5b60200260200101516200074560201b60201c565b620000dc57600080fd5b80806001019150506200009b565b505050565b6060600060805167ffffffffffffffff81111562000112576200011162000cdc565b5b604051908082528060200260200182016040528015620001415781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b8160008151811062000170576200016f62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110620001d657620001d562000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad816002815181106200023c576200023b62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110620002a257620002a162000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac8160048151811062000308576200030762000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a38816005815181106200036e576200036d62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa471965311181600681518110620003d457620003d362000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b816007815181106200043a576200043962000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff2714481600881518110620004a0576200049f62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c48160098151811062000506576200050562000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600a815181106200056c576200056b62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600b81518110620005d257620005d162000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600c8151811062000638576200063762000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081600d815181106200069e576200069d62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81600e8151811062000704576200070362000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480620007d5575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806200082057507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806200086b575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80620008b657507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000901575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806200094c57507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000997575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80620009e25750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a2d575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a7857507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ac35750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b0e575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b595750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ba4575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b600080fd5b6000819050919050565b62000bc58162000bb0565b811462000bd157600080fd5b50565b60008151905062000be58162000bba565b92915050565b60006020828403121562000c045762000c0362000bab565b5b600062000c148482850162000bd4565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600062000c598262000bb0565b915062000c668362000bb0565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161562000ca25762000ca162000c1d565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60805160a0516127a462000d54600039600081816109080152610b72015260008181610777015281816107e501528181610b9801528181610ce901526119a601526127a46000f3fe608060405234801561001057600080fd5b50600436106101ed5760003560e01c8062113e08146101f2578063015f7ed61461021057806303a1e2241461022e578063095ea7b31461024c5780630db18e371461027c57806317d7de7c146102ac57806318160ddd146102ca5780631aa3a008146102e85780631d4f9ce0146102f257806323b872dd1461032257806327e235e31461035257806329092d0e146103825780632e1a7d4d1461039e578063398b056e146103ce578063411ff497146103ec57806345f9f8251461040a57806352b41e351461042857806354755335146104445780635dc4bfd31461046257806369dc7ae41461048057806370a082311461049e578063838e7c3a146104ce578063902d55a5146104ea5780639031d9131461050857806390ff7e2e14610526578063989b6996146105445780639f0e948414610562578063a15ab08d14610580578063a39fac121461059c578063a694fc3a146105ba578063a9059cbb146105d6578063b2119eac14610606578063b49b084214610624578063c2ee3a0814610642578063db73177714610660578063dd62ed3e1461067e578063e2dc7a1a146106ae578063e79a198f146106cc578063e985e008146106d6578063e9fad8ee146106f4578063edf26d9b14610712578063fa52c7d814610742575b600080fd5b6101fa610773565b60405161020791906120ab565b60405180910390f35b610218610844565b604051610225919061210e565b60405180910390f35b61023661085c565b604051610243919061210e565b60405180910390f35b6102666004803603810190610261919061218b565b610874565b60405161027391906121e6565b60405180910390f35b61029660048036038101906102919190612201565b6108a8565b6040516102a391906121e6565b60405180910390f35b6102b46108dc565b6040516102c19190612247565b60405180910390f35b6102d2610904565b6040516102df9190612271565b60405180910390f35b6102f061092c565b005b61030c600480360381019061030791906122f1565b61092e565b60405161031991906121e6565b60405180910390f35b61033c6004803603810190610337919061233e565b610994565b60405161034991906121e6565b60405180910390f35b61036c60048036038101906103679190612201565b6109c8565b6040516103799190612271565b60405180910390f35b61039c60048036038101906103979190612201565b6109ef565b005b6103b860048036038101906103b39190612391565b610a21565b6040516103c591906121e6565b60405180910390f35b6103d6610a55565b6040516103e3919061210e565b60405180910390f35b6103f4610a6d565b604051610401919061210e565b60405180910390f35b610412610a85565b60405161041f919061210e565b60405180910390f35b610442600480360381019061043d9190612391565b610a9d565b005b61044c610acf565b604051610459919061210e565b60405180910390f35b61046a610ae7565b604051610477919061210e565b60405180910390f35b610488610aff565b604051610495919061210e565b60405180910390f35b6104b860048036038101906104b39190612201565b610b17565b6040516104c59190612271565b60405180910390f35b6104e860048036038101906104e39190612414565b610b3e565b005b6104f2610b70565b6040516104ff9190612271565b60405180910390f35b610510610b94565b60405161051d9190612271565b60405180910390f35b61052e610bbc565b60405161053b919061210e565b60405180910390f35b61054c610bd4565b604051610559919061210e565b60405180910390f35b61056a610bec565b604051610577919061210e565b60405180910390f35b61059a60048036038101906105959190612414565b610c04565b005b6105a4610c36565b6040516105b19190612532565b60405180910390f35b6105d460048036038101906105cf9190612391565b610c45565b005b6105f060048036038101906105eb919061218b565b610c77565b6040516105fd91906121e6565b60405180910390f35b61060e610cab565b60405161061b919061210e565b60405180910390f35b61062c610cc3565b604051610639919061210e565b60405180910390f35b61064a610cdb565b6040516106579190612271565b60405180910390f35b610668610ce7565b6040516106759190612271565b60405180910390f35b61069860048036038101906106939190612554565b610d0b565b6040516106a59190612271565b60405180910390f35b6106b6610d3f565b6040516106c3919061210e565b60405180910390f35b6106d4610d57565b005b6106de610d59565b6040516106eb919061210e565b60405180910390f35b6106fc610d71565b60405161070991906121e6565b60405180910390f35b61072c60048036038101906107279190612391565b610da5565b604051610739919061210e565b60405180910390f35b61075c60048036038101906107579190612201565b610dd0565b60405161076a92919061262d565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156107af576107ae61265d565b5b6040519080825280602002602001820160405280156107dd5781602001602082028036833780820191505090505b50905060005b7f000000000000000000000000000000000000000000000000000000000000000081101561084057670de0b6b3a76400008282815181106108275761082661268c565b5b60200260200101818152505080806001019150506107e3565b5090565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b838390508110156109885761096d8484838181106109535761095261268c565b5b90506020020160208101906109689190612201565b611548565b61097b57600091505061098e565b8080600101915050610932565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006109d382611548565b6109de5760006109e8565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73a7241994267682de4de7ef62f52dc2c783d1784b81565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b736eed457c20603edae50c3a112caa1a9425321bd081565b6000610b2282611548565b610b2d576000610b37565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73281754ab58391a478b7aa4e7f39991cfb41118c481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610c406119a0565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b565b732f85824b2b38f179e451988670935d315b5b969281565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610daf6119a0565b8281518110610dc157610dc061268c565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e5b57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611543565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610ee257826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611543565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f6957826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611543565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fd357826040518060600160405280602281526020016126df6022913991509150611543565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361105a57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611543565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110c457826040518060600160405280602381526020016126bc6023913991509150611543565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361114b57826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611543565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111b557826040518060600160405280602781526020016127256027913991509150611543565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361123c57826040518060400160405280601981526020017f68747470733a2f2f756d622e686173686b65792e636c6f75640000000000000081525091509150611543565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112a657826040518060600160405280602481526020016127016024913991509150611543565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361132d57826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611543565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113b457826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611543565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361143b57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611543565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114a5578260405180606001604052806023815260200161274c6023913991509150611543565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152c57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611543565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806115d7575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061162157507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061166b575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116b557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116ff575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061174957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611793575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806117dd5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611827575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061187157507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806118bb5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611905575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061194f5750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611999575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156119de576119dd61265d565b5b604051908082528060200260200182016040528015611a0c5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611a3857611a3761268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611a9b57611a9a61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611afe57611afd61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611b6157611b6061268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac81600481518110611bc457611bc361268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a3881600581518110611c2757611c2661268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa471965311181600681518110611c8a57611c8961268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b81600781518110611ced57611cec61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff2714481600881518110611d5057611d4f61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600981518110611db357611db261268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600a81518110611e1657611e1561268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600b81518110611e7957611e7861268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600c81518110611edc57611edb61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081600d81518110611f3f57611f3e61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81600e81518110611fa257611fa161268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6120228161200f565b82525050565b60006120348383612019565b60208301905092915050565b6000602082019050919050565b600061205882611fe3565b6120628185611fee565b935061206d83611fff565b8060005b8381101561209e5781516120858882612028565b975061209083612040565b925050600181019050612071565b5085935050505092915050565b600060208201905081810360008301526120c5818461204d565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006120f8826120cd565b9050919050565b612108816120ed565b82525050565b600060208201905061212360008301846120ff565b92915050565b600080fd5b600080fd5b61213c816120ed565b811461214757600080fd5b50565b60008135905061215981612133565b92915050565b6121688161200f565b811461217357600080fd5b50565b6000813590506121858161215f565b92915050565b600080604083850312156121a2576121a1612129565b5b60006121b08582860161214a565b92505060206121c185828601612176565b9150509250929050565b60008115159050919050565b6121e0816121cb565b82525050565b60006020820190506121fb60008301846121d7565b92915050565b60006020828403121561221757612216612129565b5b60006122258482850161214a565b91505092915050565b6000819050919050565b6122418161222e565b82525050565b600060208201905061225c6000830184612238565b92915050565b61226b8161200f565b82525050565b60006020820190506122866000830184612262565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126122b1576122b061228c565b5b8235905067ffffffffffffffff8111156122ce576122cd612291565b5b6020830191508360208202830111156122ea576122e9612296565b5b9250929050565b6000806020838503121561230857612307612129565b5b600083013567ffffffffffffffff8111156123265761232561212e565b5b6123328582860161229b565b92509250509250929050565b60008060006060848603121561235757612356612129565b5b60006123658682870161214a565b93505060206123768682870161214a565b925050604061238786828701612176565b9150509250925092565b6000602082840312156123a7576123a6612129565b5b60006123b584828501612176565b91505092915050565b60008083601f8401126123d4576123d361228c565b5b8235905067ffffffffffffffff8111156123f1576123f0612291565b5b60208301915083600182028301111561240d5761240c612296565b5b9250929050565b60008060006040848603121561242d5761242c612129565b5b600061243b8682870161214a565b935050602084013567ffffffffffffffff81111561245c5761245b61212e565b5b612468868287016123be565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6124a9816120ed565b82525050565b60006124bb83836124a0565b60208301905092915050565b6000602082019050919050565b60006124df82612474565b6124e9818561247f565b93506124f483612490565b8060005b8381101561252557815161250c88826124af565b9750612517836124c7565b9250506001810190506124f8565b5085935050505092915050565b6000602082019050818103600083015261254c81846124d4565b905092915050565b6000806040838503121561256b5761256a612129565b5b60006125798582860161214a565b925050602061258a8582860161214a565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156125ce5780820151818401526020810190506125b3565b838111156125dd576000848401525b50505050565b6000601f19601f8301169050919050565b60006125ff82612594565b612609818561259f565b93506126198185602086016125b0565b612622816125e3565b840191505092915050565b600060408201905061264260008301856120ff565b818103602083015261265481846125f4565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6da2646970667358221220b875faa4ff94a6ed380db1c82cfc4fcfdce28d00988b3f85c113e0332affbaa264736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101ed5760003560e01c8062113e08146101f2578063015f7ed61461021057806303a1e2241461022e578063095ea7b31461024c5780630db18e371461027c57806317d7de7c146102ac57806318160ddd146102ca5780631aa3a008146102e85780631d4f9ce0146102f257806323b872dd1461032257806327e235e31461035257806329092d0e146103825780632e1a7d4d1461039e578063398b056e146103ce578063411ff497146103ec57806345f9f8251461040a57806352b41e351461042857806354755335146104445780635dc4bfd31461046257806369dc7ae41461048057806370a082311461049e578063838e7c3a146104ce578063902d55a5146104ea5780639031d9131461050857806390ff7e2e14610526578063989b6996146105445780639f0e948414610562578063a15ab08d14610580578063a39fac121461059c578063a694fc3a146105ba578063a9059cbb146105d6578063b2119eac14610606578063b49b084214610624578063c2ee3a0814610642578063db73177714610660578063dd62ed3e1461067e578063e2dc7a1a146106ae578063e79a198f146106cc578063e985e008146106d6578063e9fad8ee146106f4578063edf26d9b14610712578063fa52c7d814610742575b600080fd5b6101fa610773565b60405161020791906120ab565b60405180910390f35b610218610844565b604051610225919061210e565b60405180910390f35b61023661085c565b604051610243919061210e565b60405180910390f35b6102666004803603810190610261919061218b565b610874565b60405161027391906121e6565b60405180910390f35b61029660048036038101906102919190612201565b6108a8565b6040516102a391906121e6565b60405180910390f35b6102b46108dc565b6040516102c19190612247565b60405180910390f35b6102d2610904565b6040516102df9190612271565b60405180910390f35b6102f061092c565b005b61030c600480360381019061030791906122f1565b61092e565b60405161031991906121e6565b60405180910390f35b61033c6004803603810190610337919061233e565b610994565b60405161034991906121e6565b60405180910390f35b61036c60048036038101906103679190612201565b6109c8565b6040516103799190612271565b60405180910390f35b61039c60048036038101906103979190612201565b6109ef565b005b6103b860048036038101906103b39190612391565b610a21565b6040516103c591906121e6565b60405180910390f35b6103d6610a55565b6040516103e3919061210e565b60405180910390f35b6103f4610a6d565b604051610401919061210e565b60405180910390f35b610412610a85565b60405161041f919061210e565b60405180910390f35b610442600480360381019061043d9190612391565b610a9d565b005b61044c610acf565b604051610459919061210e565b60405180910390f35b61046a610ae7565b604051610477919061210e565b60405180910390f35b610488610aff565b604051610495919061210e565b60405180910390f35b6104b860048036038101906104b39190612201565b610b17565b6040516104c59190612271565b60405180910390f35b6104e860048036038101906104e39190612414565b610b3e565b005b6104f2610b70565b6040516104ff9190612271565b60405180910390f35b610510610b94565b60405161051d9190612271565b60405180910390f35b61052e610bbc565b60405161053b919061210e565b60405180910390f35b61054c610bd4565b604051610559919061210e565b60405180910390f35b61056a610bec565b604051610577919061210e565b60405180910390f35b61059a60048036038101906105959190612414565b610c04565b005b6105a4610c36565b6040516105b19190612532565b60405180910390f35b6105d460048036038101906105cf9190612391565b610c45565b005b6105f060048036038101906105eb919061218b565b610c77565b6040516105fd91906121e6565b60405180910390f35b61060e610cab565b60405161061b919061210e565b60405180910390f35b61062c610cc3565b604051610639919061210e565b60405180910390f35b61064a610cdb565b6040516106579190612271565b60405180910390f35b610668610ce7565b6040516106759190612271565b60405180910390f35b61069860048036038101906106939190612554565b610d0b565b6040516106a59190612271565b60405180910390f35b6106b6610d3f565b6040516106c3919061210e565b60405180910390f35b6106d4610d57565b005b6106de610d59565b6040516106eb919061210e565b60405180910390f35b6106fc610d71565b60405161070991906121e6565b60405180910390f35b61072c60048036038101906107279190612391565b610da5565b604051610739919061210e565b60405180910390f35b61075c60048036038101906107579190612201565b610dd0565b60405161076a92919061262d565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156107af576107ae61265d565b5b6040519080825280602002602001820160405280156107dd5781602001602082028036833780820191505090505b50905060005b7f000000000000000000000000000000000000000000000000000000000000000081101561084057670de0b6b3a76400008282815181106108275761082661268c565b5b60200260200101818152505080806001019150506107e3565b5090565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b838390508110156109885761096d8484838181106109535761095261268c565b5b90506020020160208101906109689190612201565b611548565b61097b57600091505061098e565b8080600101915050610932565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006109d382611548565b6109de5760006109e8565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73a7241994267682de4de7ef62f52dc2c783d1784b81565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b736eed457c20603edae50c3a112caa1a9425321bd081565b6000610b2282611548565b610b2d576000610b37565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73281754ab58391a478b7aa4e7f39991cfb41118c481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610c406119a0565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b565b732f85824b2b38f179e451988670935d315b5b969281565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610daf6119a0565b8281518110610dc157610dc061268c565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e5b57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611543565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610ee257826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611543565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f6957826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611543565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fd357826040518060600160405280602281526020016126df6022913991509150611543565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361105a57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611543565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110c457826040518060600160405280602381526020016126bc6023913991509150611543565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361114b57826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611543565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111b557826040518060600160405280602781526020016127256027913991509150611543565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361123c57826040518060400160405280601981526020017f68747470733a2f2f756d622e686173686b65792e636c6f75640000000000000081525091509150611543565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112a657826040518060600160405280602481526020016127016024913991509150611543565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361132d57826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611543565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113b457826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611543565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361143b57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611543565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114a5578260405180606001604052806023815260200161274c6023913991509150611543565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152c57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611543565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806115d7575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061162157507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061166b575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116b557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116ff575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061174957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611793575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806117dd5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611827575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061187157507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806118bb5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611905575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061194f5750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611999575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156119de576119dd61265d565b5b604051908082528060200260200182016040528015611a0c5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611a3857611a3761268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611a9b57611a9a61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611afe57611afd61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611b6157611b6061268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac81600481518110611bc457611bc361268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a3881600581518110611c2757611c2661268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa471965311181600681518110611c8a57611c8961268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b81600781518110611ced57611cec61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff2714481600881518110611d5057611d4f61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600981518110611db357611db261268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600a81518110611e1657611e1561268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600b81518110611e7957611e7861268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600c81518110611edc57611edb61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081600d81518110611f3f57611f3e61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81600e81518110611fa257611fa161268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6120228161200f565b82525050565b60006120348383612019565b60208301905092915050565b6000602082019050919050565b600061205882611fe3565b6120628185611fee565b935061206d83611fff565b8060005b8381101561209e5781516120858882612028565b975061209083612040565b925050600181019050612071565b5085935050505092915050565b600060208201905081810360008301526120c5818461204d565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006120f8826120cd565b9050919050565b612108816120ed565b82525050565b600060208201905061212360008301846120ff565b92915050565b600080fd5b600080fd5b61213c816120ed565b811461214757600080fd5b50565b60008135905061215981612133565b92915050565b6121688161200f565b811461217357600080fd5b50565b6000813590506121858161215f565b92915050565b600080604083850312156121a2576121a1612129565b5b60006121b08582860161214a565b92505060206121c185828601612176565b9150509250929050565b60008115159050919050565b6121e0816121cb565b82525050565b60006020820190506121fb60008301846121d7565b92915050565b60006020828403121561221757612216612129565b5b60006122258482850161214a565b91505092915050565b6000819050919050565b6122418161222e565b82525050565b600060208201905061225c6000830184612238565b92915050565b61226b8161200f565b82525050565b60006020820190506122866000830184612262565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126122b1576122b061228c565b5b8235905067ffffffffffffffff8111156122ce576122cd612291565b5b6020830191508360208202830111156122ea576122e9612296565b5b9250929050565b6000806020838503121561230857612307612129565b5b600083013567ffffffffffffffff8111156123265761232561212e565b5b6123328582860161229b565b92509250509250929050565b60008060006060848603121561235757612356612129565b5b60006123658682870161214a565b93505060206123768682870161214a565b925050604061238786828701612176565b9150509250925092565b6000602082840312156123a7576123a6612129565b5b60006123b584828501612176565b91505092915050565b60008083601f8401126123d4576123d361228c565b5b8235905067ffffffffffffffff8111156123f1576123f0612291565b5b60208301915083600182028301111561240d5761240c612296565b5b9250929050565b60008060006040848603121561242d5761242c612129565b5b600061243b8682870161214a565b935050602084013567ffffffffffffffff81111561245c5761245b61212e565b5b612468868287016123be565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6124a9816120ed565b82525050565b60006124bb83836124a0565b60208301905092915050565b6000602082019050919050565b60006124df82612474565b6124e9818561247f565b93506124f483612490565b8060005b8381101561252557815161250c88826124af565b9750612517836124c7565b9250506001810190506124f8565b5085935050505092915050565b6000602082019050818103600083015261254c81846124d4565b905092915050565b6000806040838503121561256b5761256a612129565b5b60006125798582860161214a565b925050602061258a8582860161214a565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156125ce5780820151818401526020810190506125b3565b838111156125dd576000848401525b50505050565b6000601f19601f8301169050919050565b60006125ff82612594565b612609818561259f565b93506126198185602086016125b0565b612622816125e3565b840191505092915050565b600060408201905061264260008301856120ff565b818103602083015261265481846125f4565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6da2646970667358221220b875faa4ff94a6ed380db1c82cfc4fcfdce28d00988b3f85c113e0332affbaa264736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/eth_production/UniswapV3FetcherHelper.json b/deployments/eth_production/UniswapV3FetcherHelper.json index 04f1e207..b8f2cb43 100644 --- a/deployments/eth_production/UniswapV3FetcherHelper.json +++ b/deployments/eth_production/UniswapV3FetcherHelper.json @@ -1,5 +1,5 @@ { - "address": "0x5C16197460Bf145628127903d4c12a220148E200", + "address": "0xFEA1E5EfdF31B73DA3B2072Ac17799010B15B940", "abi": [ { "inputs": [ @@ -87,6 +87,11 @@ "outputs": [ { "components": [ + { + "internalType": "uint160", + "name": "sqrtPriceX96", + "type": "uint160" + }, { "internalType": "int24", "name": "tick", @@ -152,19 +157,19 @@ "type": "function" } ], - "transactionHash": "0x8108350c8696d30a5acbb37b630b37de6319e6b8801f1a166da0604afbf68fba", + "transactionHash": "0xf6a29a1f6a1050b1675f28097d443f38e1e0d73794b61779cc9ece1a57cce881", "receipt": { "to": null, "from": "0xA6e4fFa19B213AbeA258ae72e8e1a209B9E543e7", - "contractAddress": "0x5C16197460Bf145628127903d4c12a220148E200", - "transactionIndex": 255, - "gasUsed": "1797412", + "contractAddress": "0xFEA1E5EfdF31B73DA3B2072Ac17799010B15B940", + "transactionIndex": 87, + "gasUsed": "1823356", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x43455d6b16ce0141bf7cbd0bf789645e9e2fc7b2ff1ea1bd207c6ae23da1a077", - "transactionHash": "0x8108350c8696d30a5acbb37b630b37de6319e6b8801f1a166da0604afbf68fba", + "blockHash": "0xe88a460182a95d5a927cf1d3ef85b61875f6cf383c9a7cff9c358c63ac748322", + "transactionHash": "0xf6a29a1f6a1050b1675f28097d443f38e1e0d73794b61779cc9ece1a57cce881", "logs": [], - "blockNumber": 19940619, - "cumulativeGasUsed": "25012296", + "blockNumber": 21078138, + "cumulativeGasUsed": "10420089", "status": 1, "byzantium": true }, @@ -172,11 +177,11 @@ "0x1F98431c8aD98523631AE4a59f267346ea31F984", "0xFf86762915c0F1904234DB475b53E4ef904C3626" ], - "numDeployments": 2, - "solcInputHash": "7d0ce880ab90bdf9ca518a347f49d804", - "metadata": "{\"compiler\":{\"version\":\"0.8.22+commit.4fc1097e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IUniswapV3Factory\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"contract IQuoterV2\",\"name\":\"_quoter\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contract IUniswapV3Pool\",\"name\":\"pool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"base\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"quote\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"amountInDecimals\",\"type\":\"uint8\"}],\"internalType\":\"struct UniswapV3FetcherHelper.InputData[]\",\"name\":\"_data\",\"type\":\"tuple[]\"}],\"name\":\"getPrices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"price\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"internalType\":\"struct UniswapV3FetcherHelper.Price[]\",\"name\":\"prices\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IUniswapV3Pool[]\",\"name\":\"_pools\",\"type\":\"address[]\"}],\"name\":\"liquidityData\",\"outputs\":[{\"components\":[{\"internalType\":\"int24\",\"name\":\"tick\",\"type\":\"int24\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"internalType\":\"struct UniswapV3FetcherHelper.LiquidityData[]\",\"name\":\"data\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_tokens\",\"type\":\"address[]\"}],\"name\":\"tokensSymbols\",\"outputs\":[{\"internalType\":\"string[]\",\"name\":\"symbols\",\"type\":\"string[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"uniswapV3Factory\",\"outputs\":[{\"internalType\":\"contract IUniswapV3Factory\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"uniswapV3Quoter\",\"outputs\":[{\"internalType\":\"contract IQuoterV2\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getPrices((address,address,address,uint8)[])\":{\"details\":\"this method will return estimations for swap for one base token it can not be view, but to get estimation you have to call it in a static way Tokens that do not have `.decimals()` are not supported\",\"params\":{\"_data\":\"array of PriceData, each PriceData can accept multiple pools per one price, price is fetched from pool, that has biggest liquidity (quote.balanceOf(pool))\"},\"returns\":{\"prices\":\"prices normalized from input amount (10 ** prices[n].amountInDecimals) to one token price\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/fetchers/uniswapV3/UniswapV3FetcherHelper.sol\":\"UniswapV3FetcherHelper\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":0},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title The interface for the Uniswap V3 Factory\\n/// @notice The Uniswap V3 Factory facilitates creation of Uniswap V3 pools and control over the protocol fees\\ninterface IUniswapV3Factory {\\n /// @notice Emitted when the owner of the factory is changed\\n /// @param oldOwner The owner before the owner was changed\\n /// @param newOwner The owner after the owner was changed\\n event OwnerChanged(address indexed oldOwner, address indexed newOwner);\\n\\n /// @notice Emitted when a pool is created\\n /// @param token0 The first token of the pool by address sort order\\n /// @param token1 The second token of the pool by address sort order\\n /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n /// @param tickSpacing The minimum number of ticks between initialized ticks\\n /// @param pool The address of the created pool\\n event PoolCreated(\\n address indexed token0,\\n address indexed token1,\\n uint24 indexed fee,\\n int24 tickSpacing,\\n address pool\\n );\\n\\n /// @notice Emitted when a new fee amount is enabled for pool creation via the factory\\n /// @param fee The enabled fee, denominated in hundredths of a bip\\n /// @param tickSpacing The minimum number of ticks between initialized ticks for pools created with the given fee\\n event FeeAmountEnabled(uint24 indexed fee, int24 indexed tickSpacing);\\n\\n /// @notice Returns the current owner of the factory\\n /// @dev Can be changed by the current owner via setOwner\\n /// @return The address of the factory owner\\n function owner() external view returns (address);\\n\\n /// @notice Returns the tick spacing for a given fee amount, if enabled, or 0 if not enabled\\n /// @dev A fee amount can never be removed, so this value should be hard coded or cached in the calling context\\n /// @param fee The enabled fee, denominated in hundredths of a bip. Returns 0 in case of unenabled fee\\n /// @return The tick spacing\\n function feeAmountTickSpacing(uint24 fee) external view returns (int24);\\n\\n /// @notice Returns the pool address for a given pair of tokens and a fee, or address 0 if it does not exist\\n /// @dev tokenA and tokenB may be passed in either token0/token1 or token1/token0 order\\n /// @param tokenA The contract address of either token0 or token1\\n /// @param tokenB The contract address of the other token\\n /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n /// @return pool The pool address\\n function getPool(\\n address tokenA,\\n address tokenB,\\n uint24 fee\\n ) external view returns (address pool);\\n\\n /// @notice Creates a pool for the given two tokens and fee\\n /// @param tokenA One of the two tokens in the desired pool\\n /// @param tokenB The other of the two tokens in the desired pool\\n /// @param fee The desired fee for the pool\\n /// @dev tokenA and tokenB may be passed in either order: token0/token1 or token1/token0. tickSpacing is retrieved\\n /// from the fee. The call will revert if the pool already exists, the fee is invalid, or the token arguments\\n /// are invalid.\\n /// @return pool The address of the newly created pool\\n function createPool(\\n address tokenA,\\n address tokenB,\\n uint24 fee\\n ) external returns (address pool);\\n\\n /// @notice Updates the owner of the factory\\n /// @dev Must be called by the current owner\\n /// @param _owner The new owner of the factory\\n function setOwner(address _owner) external;\\n\\n /// @notice Enables a fee amount with the given tickSpacing\\n /// @dev Fee amounts may never be removed once enabled\\n /// @param fee The fee amount to enable, denominated in hundredths of a bip (i.e. 1e-6)\\n /// @param tickSpacing The spacing between ticks to be enforced for all pools created with the given fee amount\\n function enableFeeAmount(uint24 fee, int24 tickSpacing) external;\\n}\\n\",\"keccak256\":\"0xcc3d0c93fc9ac0febbe09f941b465b57f750bcf3b48432da0b97dc289cfdc489\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n IUniswapV3PoolImmutables,\\n IUniswapV3PoolState,\\n IUniswapV3PoolDerivedState,\\n IUniswapV3PoolActions,\\n IUniswapV3PoolOwnerActions,\\n IUniswapV3PoolEvents\\n{\\n\\n}\\n\",\"keccak256\":\"0xfe6113d518466cd6652c85b111e01f33eb62157f49ae5ed7d5a3947a2044adb1\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Permissionless pool actions\\n/// @notice Contains pool methods that can be called by anyone\\ninterface IUniswapV3PoolActions {\\n /// @notice Sets the initial price for the pool\\n /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\\n /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\\n function initialize(uint160 sqrtPriceX96) external;\\n\\n /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\\n /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\\n /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\\n /// on tickLower, tickUpper, the amount of liquidity, and the current price.\\n /// @param recipient The address for which the liquidity will be created\\n /// @param tickLower The lower tick of the position in which to add liquidity\\n /// @param tickUpper The upper tick of the position in which to add liquidity\\n /// @param amount The amount of liquidity to mint\\n /// @param data Any data that should be passed through to the callback\\n /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\\n /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\\n function mint(\\n address recipient,\\n int24 tickLower,\\n int24 tickUpper,\\n uint128 amount,\\n bytes calldata data\\n ) external returns (uint256 amount0, uint256 amount1);\\n\\n /// @notice Collects tokens owed to a position\\n /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\\n /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\\n /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\\n /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\\n /// @param recipient The address which should receive the fees collected\\n /// @param tickLower The lower tick of the position for which to collect fees\\n /// @param tickUpper The upper tick of the position for which to collect fees\\n /// @param amount0Requested How much token0 should be withdrawn from the fees owed\\n /// @param amount1Requested How much token1 should be withdrawn from the fees owed\\n /// @return amount0 The amount of fees collected in token0\\n /// @return amount1 The amount of fees collected in token1\\n function collect(\\n address recipient,\\n int24 tickLower,\\n int24 tickUpper,\\n uint128 amount0Requested,\\n uint128 amount1Requested\\n ) external returns (uint128 amount0, uint128 amount1);\\n\\n /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\\n /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\\n /// @dev Fees must be collected separately via a call to #collect\\n /// @param tickLower The lower tick of the position for which to burn liquidity\\n /// @param tickUpper The upper tick of the position for which to burn liquidity\\n /// @param amount How much liquidity to burn\\n /// @return amount0 The amount of token0 sent to the recipient\\n /// @return amount1 The amount of token1 sent to the recipient\\n function burn(\\n int24 tickLower,\\n int24 tickUpper,\\n uint128 amount\\n ) external returns (uint256 amount0, uint256 amount1);\\n\\n /// @notice Swap token0 for token1, or token1 for token0\\n /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\\n /// @param recipient The address to receive the output of the swap\\n /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\\n /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\\n /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\\n /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\\n /// @param data Any data to be passed through to the callback\\n /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\\n /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n\\n /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\\n /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\\n /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\\n /// with 0 amount{0,1} and sending the donation amount(s) from the callback\\n /// @param recipient The address which will receive the token0 and token1 amounts\\n /// @param amount0 The amount of token0 to send\\n /// @param amount1 The amount of token1 to send\\n /// @param data Any data to be passed through to the callback\\n function flash(\\n address recipient,\\n uint256 amount0,\\n uint256 amount1,\\n bytes calldata data\\n ) external;\\n\\n /// @notice Increase the maximum number of price and liquidity observations that this pool will store\\n /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\\n /// the input observationCardinalityNext.\\n /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\\n function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;\\n}\\n\",\"keccak256\":\"0x9453dd0e7442188667d01d9b65de3f1e14e9511ff3e303179a15f6fc267f7634\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that is not stored\\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\\n/// blockchain. The functions here may have variable gas costs.\\ninterface IUniswapV3PoolDerivedState {\\n /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\\n /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\\n /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\\n /// you must call it with secondsAgos = [3600, 0].\\n /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\\n /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\\n /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\\n /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\\n /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\\n /// timestamp\\n function observe(uint32[] calldata secondsAgos)\\n external\\n view\\n returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);\\n\\n /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\\n /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\\n /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\\n /// snapshot is taken and the second snapshot is taken.\\n /// @param tickLower The lower tick of the range\\n /// @param tickUpper The upper tick of the range\\n /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\\n /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\\n /// @return secondsInside The snapshot of seconds per liquidity for the range\\n function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\\n external\\n view\\n returns (\\n int56 tickCumulativeInside,\\n uint160 secondsPerLiquidityInsideX128,\\n uint32 secondsInside\\n );\\n}\\n\",\"keccak256\":\"0xe603ac5b17ecdee73ba2b27efdf386c257a19c14206e87eee77e2017b742d9e5\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Events emitted by a pool\\n/// @notice Contains all events emitted by the pool\\ninterface IUniswapV3PoolEvents {\\n /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\\n /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\\n /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\\n /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\\n event Initialize(uint160 sqrtPriceX96, int24 tick);\\n\\n /// @notice Emitted when liquidity is minted for a given position\\n /// @param sender The address that minted the liquidity\\n /// @param owner The owner of the position and recipient of any minted liquidity\\n /// @param tickLower The lower tick of the position\\n /// @param tickUpper The upper tick of the position\\n /// @param amount The amount of liquidity minted to the position range\\n /// @param amount0 How much token0 was required for the minted liquidity\\n /// @param amount1 How much token1 was required for the minted liquidity\\n event Mint(\\n address sender,\\n address indexed owner,\\n int24 indexed tickLower,\\n int24 indexed tickUpper,\\n uint128 amount,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n /// @notice Emitted when fees are collected by the owner of a position\\n /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\\n /// @param owner The owner of the position for which fees are collected\\n /// @param tickLower The lower tick of the position\\n /// @param tickUpper The upper tick of the position\\n /// @param amount0 The amount of token0 fees collected\\n /// @param amount1 The amount of token1 fees collected\\n event Collect(\\n address indexed owner,\\n address recipient,\\n int24 indexed tickLower,\\n int24 indexed tickUpper,\\n uint128 amount0,\\n uint128 amount1\\n );\\n\\n /// @notice Emitted when a position's liquidity is removed\\n /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\\n /// @param owner The owner of the position for which liquidity is removed\\n /// @param tickLower The lower tick of the position\\n /// @param tickUpper The upper tick of the position\\n /// @param amount The amount of liquidity to remove\\n /// @param amount0 The amount of token0 withdrawn\\n /// @param amount1 The amount of token1 withdrawn\\n event Burn(\\n address indexed owner,\\n int24 indexed tickLower,\\n int24 indexed tickUpper,\\n uint128 amount,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n /// @notice Emitted by the pool for any swaps between token0 and token1\\n /// @param sender The address that initiated the swap call, and that received the callback\\n /// @param recipient The address that received the output of the swap\\n /// @param amount0 The delta of the token0 balance of the pool\\n /// @param amount1 The delta of the token1 balance of the pool\\n /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\\n /// @param liquidity The liquidity of the pool after the swap\\n /// @param tick The log base 1.0001 of price of the pool after the swap\\n event Swap(\\n address indexed sender,\\n address indexed recipient,\\n int256 amount0,\\n int256 amount1,\\n uint160 sqrtPriceX96,\\n uint128 liquidity,\\n int24 tick\\n );\\n\\n /// @notice Emitted by the pool for any flashes of token0/token1\\n /// @param sender The address that initiated the swap call, and that received the callback\\n /// @param recipient The address that received the tokens from flash\\n /// @param amount0 The amount of token0 that was flashed\\n /// @param amount1 The amount of token1 that was flashed\\n /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\\n /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\\n event Flash(\\n address indexed sender,\\n address indexed recipient,\\n uint256 amount0,\\n uint256 amount1,\\n uint256 paid0,\\n uint256 paid1\\n );\\n\\n /// @notice Emitted by the pool for increases to the number of observations that can be stored\\n /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\\n /// just before a mint/swap/burn.\\n /// @param observationCardinalityNextOld The previous value of the next observation cardinality\\n /// @param observationCardinalityNextNew The updated value of the next observation cardinality\\n event IncreaseObservationCardinalityNext(\\n uint16 observationCardinalityNextOld,\\n uint16 observationCardinalityNextNew\\n );\\n\\n /// @notice Emitted when the protocol fee is changed by the pool\\n /// @param feeProtocol0Old The previous value of the token0 protocol fee\\n /// @param feeProtocol1Old The previous value of the token1 protocol fee\\n /// @param feeProtocol0New The updated value of the token0 protocol fee\\n /// @param feeProtocol1New The updated value of the token1 protocol fee\\n event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);\\n\\n /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\\n /// @param sender The address that collects the protocol fees\\n /// @param recipient The address that receives the collected protocol fees\\n /// @param amount0 The amount of token0 protocol fees that is withdrawn\\n /// @param amount0 The amount of token1 protocol fees that is withdrawn\\n event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);\\n}\\n\",\"keccak256\":\"0x8071514d0fe5d17d6fbd31c191cdfb703031c24e0ece3621d88ab10e871375cd\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that never changes\\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\\ninterface IUniswapV3PoolImmutables {\\n /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\\n /// @return The contract address\\n function factory() external view returns (address);\\n\\n /// @notice The first of the two tokens of the pool, sorted by address\\n /// @return The token contract address\\n function token0() external view returns (address);\\n\\n /// @notice The second of the two tokens of the pool, sorted by address\\n /// @return The token contract address\\n function token1() external view returns (address);\\n\\n /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\\n /// @return The fee\\n function fee() external view returns (uint24);\\n\\n /// @notice The pool tick spacing\\n /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\\n /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\\n /// This value is an int24 to avoid casting even though it is always positive.\\n /// @return The tick spacing\\n function tickSpacing() external view returns (int24);\\n\\n /// @notice The maximum amount of position liquidity that can use any tick in the range\\n /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\\n /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\\n /// @return The max amount of liquidity per tick\\n function maxLiquidityPerTick() external view returns (uint128);\\n}\\n\",\"keccak256\":\"0xf6e5d2cd1139c4c276bdbc8e1d2b256e456c866a91f1b868da265c6d2685c3f7\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Permissioned pool actions\\n/// @notice Contains pool methods that may only be called by the factory owner\\ninterface IUniswapV3PoolOwnerActions {\\n /// @notice Set the denominator of the protocol's % share of the fees\\n /// @param feeProtocol0 new protocol fee for token0 of the pool\\n /// @param feeProtocol1 new protocol fee for token1 of the pool\\n function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\\n\\n /// @notice Collect the protocol fee accrued to the pool\\n /// @param recipient The address to which collected protocol fees should be sent\\n /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\\n /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\\n /// @return amount0 The protocol fee collected in token0\\n /// @return amount1 The protocol fee collected in token1\\n function collectProtocol(\\n address recipient,\\n uint128 amount0Requested,\\n uint128 amount1Requested\\n ) external returns (uint128 amount0, uint128 amount1);\\n}\\n\",\"keccak256\":\"0x759b78a2918af9e99e246dc3af084f654e48ef32bb4e4cb8a966aa3dcaece235\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n /// when accessed externally.\\n /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n /// boundary.\\n /// observationIndex The index of the last oracle observation that was written,\\n /// observationCardinality The current maximum number of observations stored in the pool,\\n /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n /// feeProtocol The protocol fee for both tokens of the pool.\\n /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n /// unlocked Whether the pool is currently locked to reentrancy\\n function slot0()\\n external\\n view\\n returns (\\n uint160 sqrtPriceX96,\\n int24 tick,\\n uint16 observationIndex,\\n uint16 observationCardinality,\\n uint16 observationCardinalityNext,\\n uint8 feeProtocol,\\n bool unlocked\\n );\\n\\n /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n /// @dev This value can overflow the uint256\\n function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n /// @dev This value can overflow the uint256\\n function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n /// @notice The amounts of token0 and token1 that are owed to the protocol\\n /// @dev Protocol fees will never exceed uint128 max in either token\\n function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n /// @notice The currently in range liquidity available to the pool\\n /// @dev This value has no relationship to the total liquidity across all ticks\\n function liquidity() external view returns (uint128);\\n\\n /// @notice Look up information about a specific tick in the pool\\n /// @param tick The tick to look up\\n /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n /// tick upper,\\n /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n /// a specific position.\\n function ticks(int24 tick)\\n external\\n view\\n returns (\\n uint128 liquidityGross,\\n int128 liquidityNet,\\n uint256 feeGrowthOutside0X128,\\n uint256 feeGrowthOutside1X128,\\n int56 tickCumulativeOutside,\\n uint160 secondsPerLiquidityOutsideX128,\\n uint32 secondsOutside,\\n bool initialized\\n );\\n\\n /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n /// @notice Returns the information about a position by the position's key\\n /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n /// @return _liquidity The amount of liquidity in the position,\\n /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n function positions(bytes32 key)\\n external\\n view\\n returns (\\n uint128 _liquidity,\\n uint256 feeGrowthInside0LastX128,\\n uint256 feeGrowthInside1LastX128,\\n uint128 tokensOwed0,\\n uint128 tokensOwed1\\n );\\n\\n /// @notice Returns data about a specific observation index\\n /// @param index The element of the observations array to fetch\\n /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n /// ago, rather than at a specific index in the array.\\n /// @return blockTimestamp The timestamp of the observation,\\n /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n /// Returns initialized whether the observation has been initialized and the values are safe to use\\n function observations(uint256 index)\\n external\\n view\\n returns (\\n uint32 blockTimestamp,\\n int56 tickCumulative,\\n uint160 secondsPerLiquidityCumulativeX128,\\n bool initialized\\n );\\n}\\n\",\"keccak256\":\"0x852dc1f5df7dcf7f11e7bb3eed79f0cea72ad4b25f6a9d2c35aafb48925fd49f\",\"license\":\"GPL-2.0-or-later\"},\"contracts/fetchers/CommonFetcher.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\npragma solidity ^0.8.0;\\n\\ncontract CommonFetcher {\\n uint256 internal constant _DECIMALS = 18;\\n bytes4 internal constant _DECIMALS_SELECTOR = bytes4(keccak256(\\\"decimals()\\\"));\\n\\n function _decimals(address _token) internal view virtual returns (uint256 decimals, bool success) {\\n bytes memory data;\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (success, data) = _token.staticcall(abi.encode(_DECIMALS_SELECTOR));\\n if (success && data.length != 0) decimals = abi.decode(data, (uint256));\\n else success = false;\\n }\\n\\n function _normalizeOneTokenPrice(\\n uint256 _amountInDecimals,\\n uint256 _baseDecimals,\\n uint256 _quoteDecimals,\\n uint256 _price\\n )\\n internal\\n pure\\n virtual\\n returns (uint256 normalizedPrice)\\n {\\n // normalize price from `amountInDecimals` to `oneToken`\\n if (_amountInDecimals == _baseDecimals) {\\n normalizedPrice = _price;\\n }\\n else if (_amountInDecimals < _baseDecimals) {\\n normalizedPrice = _price * (10 ** (_baseDecimals - _amountInDecimals));\\n } else {\\n normalizedPrice = _price / (10 ** (_amountInDecimals - _baseDecimals));\\n }\\n\\n // normalize price to 18 decimals\\n if (_quoteDecimals == _DECIMALS) {\\n // price OK\\n } else if (_quoteDecimals > _DECIMALS) {\\n normalizedPrice /= 10 ** (_quoteDecimals - _DECIMALS);\\n } else {\\n normalizedPrice *= 10 ** (_DECIMALS - _quoteDecimals);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x92c7c83829d8e2d5f38048903e63495f9ac6cf28b417bfff6ec6b1431845df50\",\"license\":\"UNLICENSED\"},\"contracts/fetchers/uniswapV3/UniswapV3FetcherHelper.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.22;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport {IUniswapV3Factory} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IUniswapV3PoolImmutables} from \\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\\\";\\nimport {IQuoterV2} from \\\"gitmodules/uniswap/v3-periphery/contracts/interfaces/IQuoterV2.sol\\\";\\n\\nimport {CommonFetcher} from \\\"../CommonFetcher.sol\\\";\\n\\ncontract UniswapV3FetcherHelper is CommonFetcher {\\n struct InputData {\\n IUniswapV3Pool pool;\\n address base;\\n address quote;\\n uint8 amountInDecimals;\\n }\\n\\n /// @param price is amount out (normalized to 18 decimals) returned by Uniswap pool for 1 quote token\\n struct Price {\\n uint256 price;\\n bool success;\\n }\\n\\n struct LiquidityData {\\n int24 tick;\\n uint256 liquidity;\\n }\\n\\n bytes4 internal constant _SYMBOL_SELECTOR = bytes4(keccak256(\\\"symbol()\\\"));\\n\\n IUniswapV3Factory immutable public uniswapV3Factory;\\n IQuoterV2 immutable public uniswapV3Quoter;\\n\\n constructor(IUniswapV3Factory _factory, IQuoterV2 _quoter) {\\n uniswapV3Factory = _factory;\\n uniswapV3Quoter = _quoter;\\n }\\n\\n /// @dev this method will return estimations for swap for one base token\\n /// it can not be view, but to get estimation you have to call it in a static way\\n /// Tokens that do not have `.decimals()` are not supported\\n /// @param _data array of PriceData, each PriceData can accept multiple pools per one price, price is fetched from\\n /// pool, that has biggest liquidity (quote.balanceOf(pool))\\n /// @return prices prices normalized from input amount (10 ** prices[n].amountInDecimals) to one token price\\n function getPrices(InputData[] calldata _data)\\n external\\n virtual\\n returns (Price[] memory prices, uint256 timestamp)\\n {\\n timestamp = block.timestamp;\\n uint256 n = _data.length;\\n prices = new Price[](n);\\n\\n for (uint256 i = 0; i < n; i++) {\\n prices[i] = _getPrice(_data[i]);\\n }\\n }\\n\\n function tokensSymbols(address[] calldata _tokens) external view virtual returns (string[] memory symbols) {\\n uint256 n = _tokens.length;\\n symbols = new string[](n);\\n\\n for (uint256 i = 0; i < n; i++) {\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory data) = _tokens[i].staticcall(abi.encode(_SYMBOL_SELECTOR));\\n\\n symbols[i] = success\\n ? data.length == 32 ? string(abi.encodePacked(data)) : abi.decode(data, (string))\\n : \\\"\\\";\\n }\\n }\\n\\n function liquidityData(IUniswapV3Pool[] calldata _pools)\\n external\\n view\\n virtual\\n returns (LiquidityData[] memory data)\\n {\\n uint256 n = _pools.length;\\n data = new LiquidityData[](n);\\n\\n for (uint256 i = 0; i < n; i++) {\\n IUniswapV3Pool pool = _pools[i];\\n (, data[i].tick,,,,,) = pool.slot0();\\n data[i].liquidity = pool.liquidity();\\n }\\n }\\n\\n function _getPrice(InputData memory _data) internal virtual returns (Price memory price) {\\n (uint256 baseDecimals, bool baseHasDecimals) = _decimals(_data.base);\\n if (!baseHasDecimals) return price;\\n\\n (uint256 quoteDecimals, bool quoteHasDecimals) = _decimals(_data.quote);\\n if (!quoteHasDecimals) return price;\\n\\n if (address(_data.pool) == address(0)) return price;\\n\\n (uint24 fee, bool success) = _getPoolFee(_data.pool);\\n if (!success) return price;\\n\\n if (address(_data.pool) != _getPool(_data.base, _data.quote, fee)) return price;\\n\\n IQuoterV2.QuoteExactInputSingleParams memory params = IQuoterV2.QuoteExactInputSingleParams({\\n tokenIn: _data.base,\\n tokenOut: _data.quote,\\n amountIn: 10 ** _data.amountInDecimals,\\n fee: fee,\\n sqrtPriceLimitX96: 0\\n });\\n\\n try uniswapV3Quoter.quoteExactInputSingle(params)\\n returns (uint256 tokenPrice, uint160, uint32, uint256)\\n {\\n price.price = _normalizeOneTokenPrice(_data.amountInDecimals, baseDecimals, quoteDecimals, tokenPrice);\\n price.success = true;\\n } catch (bytes memory) {\\n // continue;\\n }\\n }\\n\\n function _getPool(address _token0, address _token1, uint24 _fee) internal view virtual returns (address pool) {\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory data) = address(uniswapV3Factory).staticcall(\\n abi.encodeWithSelector(IUniswapV3Factory.getPool.selector, _token0, _token1, _fee)\\n );\\n\\n if (success) pool = abi.decode(data, (address));\\n }\\n\\n function _getPoolFee(IUniswapV3Pool _pool) internal view virtual returns (uint24 fee, bool success) {\\n bytes memory data;\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (success, data) = address(_pool).staticcall(abi.encodeWithSelector(IUniswapV3PoolImmutables.fee.selector));\\n\\n if (data.length == 0) {\\n success = false;\\n } else if (success) {\\n fee = abi.decode(data, (uint24));\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2c9a1f2f710822bed806d6a234060793dbea3566855d9724fb27d494b58fcd6d\",\"license\":\"MIT\"},\"gitmodules/uniswap/v3-periphery/contracts/interfaces/IQuoterV2.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title QuoterV2 Interface\\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps.\\n/// @notice For each pool also tells you the number of initialized ticks crossed and the sqrt price of the pool after the swap.\\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\\ninterface IQuoterV2 {\\n /// @notice Returns the amount out received for a given exact input swap without executing the swap\\n /// @param path The path of the swap, i.e. each token pair and the pool fee\\n /// @param amountIn The amount of the first token to swap\\n /// @return amountOut The amount of the last token that would be received\\n /// @return sqrtPriceX96AfterList List of the sqrt price after the swap for each pool in the path\\n /// @return initializedTicksCrossedList List of the initialized ticks that the swap crossed for each pool in the path\\n /// @return gasEstimate The estimate of the gas that the swap consumes\\n function quoteExactInput(bytes memory path, uint256 amountIn)\\n external\\n returns (\\n uint256 amountOut,\\n uint160[] memory sqrtPriceX96AfterList,\\n uint32[] memory initializedTicksCrossedList,\\n uint256 gasEstimate\\n );\\n\\n struct QuoteExactInputSingleParams {\\n address tokenIn;\\n address tokenOut;\\n uint256 amountIn;\\n uint24 fee;\\n uint160 sqrtPriceLimitX96;\\n }\\n\\n /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\\n /// @param params The params for the quote, encoded as `QuoteExactInputSingleParams`\\n /// tokenIn The token being swapped in\\n /// tokenOut The token being swapped out\\n /// fee The fee of the token pool to consider for the pair\\n /// amountIn The desired input amount\\n /// sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n /// @return amountOut The amount of `tokenOut` that would be received\\n /// @return sqrtPriceX96After The sqrt price of the pool after the swap\\n /// @return initializedTicksCrossed The number of initialized ticks that the swap crossed\\n /// @return gasEstimate The estimate of the gas that the swap consumes\\n function quoteExactInputSingle(QuoteExactInputSingleParams memory params)\\n external\\n returns (\\n uint256 amountOut,\\n uint160 sqrtPriceX96After,\\n uint32 initializedTicksCrossed,\\n uint256 gasEstimate\\n );\\n\\n /// @notice Returns the amount in required for a given exact output swap without executing the swap\\n /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\\n /// @param amountOut The amount of the last token to receive\\n /// @return amountIn The amount of first token required to be paid\\n /// @return sqrtPriceX96AfterList List of the sqrt price after the swap for each pool in the path\\n /// @return initializedTicksCrossedList List of the initialized ticks that the swap crossed for each pool in the path\\n /// @return gasEstimate The estimate of the gas that the swap consumes\\n function quoteExactOutput(bytes memory path, uint256 amountOut)\\n external\\n returns (\\n uint256 amountIn,\\n uint160[] memory sqrtPriceX96AfterList,\\n uint32[] memory initializedTicksCrossedList,\\n uint256 gasEstimate\\n );\\n\\n struct QuoteExactOutputSingleParams {\\n address tokenIn;\\n address tokenOut;\\n uint256 amount;\\n uint24 fee;\\n uint160 sqrtPriceLimitX96;\\n }\\n\\n /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\\n /// @param params The params for the quote, encoded as `QuoteExactOutputSingleParams`\\n /// tokenIn The token being swapped in\\n /// tokenOut The token being swapped out\\n /// fee The fee of the token pool to consider for the pair\\n /// amountOut The desired output amount\\n /// sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\\n /// @return sqrtPriceX96After The sqrt price of the pool after the swap\\n /// @return initializedTicksCrossed The number of initialized ticks that the swap crossed\\n /// @return gasEstimate The estimate of the gas that the swap consumes\\n function quoteExactOutputSingle(QuoteExactOutputSingleParams memory params)\\n external\\n returns (\\n uint256 amountIn,\\n uint160 sqrtPriceX96After,\\n uint32 initializedTicksCrossed,\\n uint256 gasEstimate\\n );\\n}\\n\",\"keccak256\":\"0x7e931f0cd34811851031c4f1318f59b4a4b427a2d2e2968b8e5ed87a9f7f89d6\",\"license\":\"GPL-2.0-or-later\"}},\"version\":1}", - "bytecode": "0x60c06040523480156200001157600080fd5b506040516200215b3803806200215b83398181016040528101906200003791906200016a565b8173ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff16815250505050620001b1565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620000d982620000ac565b9050919050565b6000620000ed82620000cc565b9050919050565b620000ff81620000e0565b81146200010b57600080fd5b50565b6000815190506200011f81620000f4565b92915050565b60006200013282620000cc565b9050919050565b620001448162000125565b81146200015057600080fd5b50565b600081519050620001648162000139565b92915050565b60008060408385031215620001845762000183620000a7565b5b600062000194858286016200010e565b9250506020620001a78582860162000153565b9150509250929050565b60805160a051611f76620001e5600039600081816104f501526107a00152600081816105190152610ab40152611f766000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80631d20d10a1461005c5780634757efc11461008c5780634d20d0f8146100bc5780635b549182146100da578063ff514fa3146100f8575b600080fd5b61007660048036038101906100719190610d64565b610129565b6040516100839190610ec4565b60405180910390f35b6100a660048036038101906100a19190610f3c565b610328565b6040516100b391906110db565b60405180910390f35b6100c46104f3565b6040516100d1919061117c565b60405180910390f35b6100e2610517565b6040516100ef91906111b8565b60405180910390f35b610112600480360381019061010d9190611229565b61053b565b60405161012092919061137e565b60405180910390f35b606060008383905090508067ffffffffffffffff81111561014d5761014c6113ae565b5b60405190808252806020026020018201604052801561018657816020015b610173610cb2565b81526020019060019003908161016b5790505b50915060005b818110156103205760008585838181106101a9576101a86113dd565b5b90506020020160208101906101be919061145c565b90508073ffffffffffffffffffffffffffffffffffffffff16633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa15801561020b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061022f9190611580565b90919293949550909192935090919250909150905050848381518110610258576102576113dd565b5b60200260200101516000018160020b60020b815250508073ffffffffffffffffffffffffffffffffffffffff16631a6865026040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102dd919061166a565b6fffffffffffffffffffffffffffffffff16848381518110610302576103016113dd565b5b6020026020010151602001818152505050808060010191505061018c565b505092915050565b606060008383905090508067ffffffffffffffff81111561034c5761034b6113ae565b5b60405190808252806020026020018201604052801561037f57816020015b606081526020019060019003908161036a5790505b50915060005b818110156104eb576000808686848181106103a3576103a26113dd565b5b90506020020160208101906103b891906116c3565b73ffffffffffffffffffffffffffffffffffffffff167f95d89b41e2f5f391a79ec54e9d87c79d6e777c63e32c28da95b4e9e4a79250ec6040516020016103ff919061172b565b60405160208183030381529060405260405161041b919061178d565b600060405180830381855afa9150503d8060008114610456576040519150601f19603f3d011682016040523d82523d6000602084013e61045b565b606091505b50915091508161047a57604051806020016040528060008152506104be565b602081511461049c57808060200190518101906104979190611896565b6104bd565b806040516020016104ad919061178d565b6040516020818303038152906040525b5b8584815181106104d1576104d06113dd565b5b602002602001018190525050508080600101915050610385565b505092915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6060600042905060008484905090508067ffffffffffffffff811115610564576105636113ae565b5b60405190808252806020026020018201604052801561059d57816020015b61058a610ccf565b8152602001906001900390816105825790505b50925060005b81811015610607576105dc8686838181106105c1576105c06113dd565b5b9050608002018036038101906105d79190611971565b610610565b8482815181106105ef576105ee6113dd565b5b602002602001018190525080806001019150506105a3565b50509250929050565b610618610ccf565b60008061062884602001516108ae565b91509150806106385750506108a9565b60008061064886604001516108ae565b915091508061065a57505050506108a9565b600073ffffffffffffffffffffffffffffffffffffffff16866000015173ffffffffffffffffffffffffffffffffffffffff160361069b57505050506108a9565b6000806106ab886000015161099a565b91509150806106bf575050505050506108a9565b6106d28860200151896040015184610aad565b73ffffffffffffffffffffffffffffffffffffffff16886000015173ffffffffffffffffffffffffffffffffffffffff1614610713575050505050506108a9565b60006040518060a001604052808a6020015173ffffffffffffffffffffffffffffffffffffffff1681526020018a6040015173ffffffffffffffffffffffffffffffffffffffff1681526020018a60600151600a6107719190611b00565b81526020018462ffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681525090507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663c6a5026a826040518263ffffffff1660e01b81526004016107f79190611bef565b6080604051808303816000875af192505050801561083357506040513d601f19601f820116820180604052508101906108309190611c72565b60015b61086f573d8060008114610863576040519150601f19603f3d011682016040523d82523d6000602084013e610868565b606091505b50506108a1565b6108828d6060015160ff168c8b87610bdb565b8c600001818152505060018c6020019015159081151581525050505050505b505050505050505b919050565b60008060608373ffffffffffffffffffffffffffffffffffffffff167f313ce567add4d438edf58b94ff345d7d38c45b17dfc0f947988d7819dca364f96040516020016108fb919061172b565b604051602081830303815290604052604051610917919061178d565b600060405180830381855afa9150503d8060008114610952576040519150601f19603f3d011682016040523d82523d6000602084013e610957565b606091505b50809250819350505081801561096f57506000815114155b1561098f57808060200190518101906109889190611cd9565b9250610994565b600091505b50915091565b60008060608373ffffffffffffffffffffffffffffffffffffffff1663ddca3f4360e01b604051602401604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610a2e919061178d565b600060405180830381855afa9150503d8060008114610a69576040519150601f19603f3d011682016040523d82523d6000602084013e610a6e565b606091505b5080925081935050506000815103610a895760009150610aa7565b8115610aa65780806020019051810190610aa39190611d32565b92505b5b50915091565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16631698ee8260e01b878787604051602401610b0693929190611d7d565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610b70919061178d565b600060405180830381855afa9150503d8060008114610bab576040519150601f19603f3d011682016040523d82523d6000602084013e610bb0565b606091505b50915091508115610bd25780806020019051810190610bcf9190611df2565b92505b50509392505050565b6000838503610bec57819050610c45565b83851015610c1e578484610c009190611e1f565b600a610c0c9190611e53565b82610c179190611e9e565b9050610c44565b8385610c2a9190611e1f565b600a610c369190611e53565b82610c419190611f0f565b90505b5b6012830315610caa576012831115610c8257601283610c649190611e1f565b600a610c709190611e53565b81610c7b9190611f0f565b9050610ca9565b826012610c8f9190611e1f565b600a610c9b9190611e53565b81610ca69190611e9e565b90505b5b949350505050565b6040518060400160405280600060020b8152602001600081525090565b6040518060400160405280600081526020016000151581525090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b60008083601f840112610d2457610d23610cff565b5b8235905067ffffffffffffffff811115610d4157610d40610d04565b5b602083019150836020820283011115610d5d57610d5c610d09565b5b9250929050565b60008060208385031215610d7b57610d7a610cf5565b5b600083013567ffffffffffffffff811115610d9957610d98610cfa565b5b610da585828601610d0e565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60008160020b9050919050565b610df381610ddd565b82525050565b6000819050919050565b610e0c81610df9565b82525050565b604082016000820151610e286000850182610dea565b506020820151610e3b6020850182610e03565b50505050565b6000610e4d8383610e12565b60408301905092915050565b6000602082019050919050565b6000610e7182610db1565b610e7b8185610dbc565b9350610e8683610dcd565b8060005b83811015610eb7578151610e9e8882610e41565b9750610ea983610e59565b925050600181019050610e8a565b5085935050505092915050565b60006020820190508181036000830152610ede8184610e66565b905092915050565b60008083601f840112610efc57610efb610cff565b5b8235905067ffffffffffffffff811115610f1957610f18610d04565b5b602083019150836020820283011115610f3557610f34610d09565b5b9250929050565b60008060208385031215610f5357610f52610cf5565b5b600083013567ffffffffffffffff811115610f7157610f70610cfa565b5b610f7d85828601610ee6565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610fef578082015181840152602081019050610fd4565b60008484015250505050565b6000601f19601f8301169050919050565b600061101782610fb5565b6110218185610fc0565b9350611031818560208601610fd1565b61103a81610ffb565b840191505092915050565b6000611051838361100c565b905092915050565b6000602082019050919050565b600061107182610f89565b61107b8185610f94565b93508360208202850161108d85610fa5565b8060005b858110156110c957848403895281516110aa8582611045565b94506110b583611059565b925060208a01995050600181019050611091565b50829750879550505050505092915050565b600060208201905081810360008301526110f58184611066565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061114261113d611138846110fd565b61111d565b6110fd565b9050919050565b600061115482611127565b9050919050565b600061116682611149565b9050919050565b6111768161115b565b82525050565b6000602082019050611191600083018461116d565b92915050565b60006111a282611149565b9050919050565b6111b281611197565b82525050565b60006020820190506111cd60008301846111a9565b92915050565b60008083601f8401126111e9576111e8610cff565b5b8235905067ffffffffffffffff81111561120657611205610d04565b5b60208301915083608082028301111561122257611221610d09565b5b9250929050565b600080602083850312156112405761123f610cf5565b5b600083013567ffffffffffffffff81111561125e5761125d610cfa565b5b61126a858286016111d3565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60008115159050919050565b6112b7816112a2565b82525050565b6040820160008201516112d36000850182610e03565b5060208201516112e660208501826112ae565b50505050565b60006112f883836112bd565b60408301905092915050565b6000602082019050919050565b600061131c82611276565b6113268185611281565b935061133183611292565b8060005b8381101561136257815161134988826112ec565b975061135483611304565b925050600181019050611335565b5085935050505092915050565b61137881610df9565b82525050565b600060408201905081810360008301526113988185611311565b90506113a7602083018461136f565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000611417826110fd565b9050919050565b60006114298261140c565b9050919050565b6114398161141e565b811461144457600080fd5b50565b60008135905061145681611430565b92915050565b60006020828403121561147257611471610cf5565b5b600061148084828501611447565b91505092915050565b611492816110fd565b811461149d57600080fd5b50565b6000815190506114af81611489565b92915050565b6114be81610ddd565b81146114c957600080fd5b50565b6000815190506114db816114b5565b92915050565b600061ffff82169050919050565b6114f8816114e1565b811461150357600080fd5b50565b600081519050611515816114ef565b92915050565b600060ff82169050919050565b6115318161151b565b811461153c57600080fd5b50565b60008151905061154e81611528565b92915050565b61155d816112a2565b811461156857600080fd5b50565b60008151905061157a81611554565b92915050565b600080600080600080600060e0888a03121561159f5761159e610cf5565b5b60006115ad8a828b016114a0565b97505060206115be8a828b016114cc565b96505060406115cf8a828b01611506565b95505060606115e08a828b01611506565b94505060806115f18a828b01611506565b93505060a06116028a828b0161153f565b92505060c06116138a828b0161156b565b91505092959891949750929550565b60006fffffffffffffffffffffffffffffffff82169050919050565b61164781611622565b811461165257600080fd5b50565b6000815190506116648161163e565b92915050565b6000602082840312156116805761167f610cf5565b5b600061168e84828501611655565b91505092915050565b6116a08161140c565b81146116ab57600080fd5b50565b6000813590506116bd81611697565b92915050565b6000602082840312156116d9576116d8610cf5565b5b60006116e7848285016116ae565b91505092915050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b611725816116f0565b82525050565b6000602082019050611740600083018461171c565b92915050565b600081519050919050565b600081905092915050565b600061176782611746565b6117718185611751565b9350611781818560208601610fd1565b80840191505092915050565b6000611799828461175c565b915081905092915050565b600080fd5b6117b282610ffb565b810181811067ffffffffffffffff821117156117d1576117d06113ae565b5b80604052505050565b60006117e4610ceb565b90506117f082826117a9565b919050565b600067ffffffffffffffff8211156118105761180f6113ae565b5b61181982610ffb565b9050602081019050919050565b6000611839611834846117f5565b6117da565b905082815260208101848484011115611855576118546117a4565b5b611860848285610fd1565b509392505050565b600082601f83011261187d5761187c610cff565b5b815161188d848260208601611826565b91505092915050565b6000602082840312156118ac576118ab610cf5565b5b600082015167ffffffffffffffff8111156118ca576118c9610cfa565b5b6118d684828501611868565b91505092915050565b600080fd5b6000813590506118f381611528565b92915050565b60006080828403121561190f5761190e6118df565b5b61191960806117da565b9050600061192984828501611447565b600083015250602061193d848285016116ae565b6020830152506040611951848285016116ae565b6040830152506060611965848285016118e4565b60608301525092915050565b60006080828403121561198757611986610cf5565b5b6000611995848285016118f9565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008160011c9050919050565b6000808291508390505b6001851115611a2457808604811115611a00576119ff61199e565b5b6001851615611a0f5780820291505b8081029050611a1d856119cd565b94506119e4565b94509492505050565b600082611a3d5760019050611af9565b81611a4b5760009050611af9565b8160018114611a615760028114611a6b57611a9a565b6001915050611af9565b60ff841115611a7d57611a7c61199e565b5b8360020a915084821115611a9457611a9361199e565b5b50611af9565b5060208310610133831016604e8410600b8410161715611acf5782820a905083811115611aca57611ac961199e565b5b611af9565b611adc84848460016119da565b92509050818404811115611af357611af261199e565b5b81810290505b9392505050565b6000611b0b82610df9565b9150611b168361151b565b9250611b437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484611a2d565b905092915050565b611b548161140c565b82525050565b600062ffffff82169050919050565b611b7281611b5a565b82525050565b611b81816110fd565b82525050565b60a082016000820151611b9d6000850182611b4b565b506020820151611bb06020850182611b4b565b506040820151611bc36040850182610e03565b506060820151611bd66060850182611b69565b506080820151611be96080850182611b78565b50505050565b600060a082019050611c046000830184611b87565b92915050565b611c1381610df9565b8114611c1e57600080fd5b50565b600081519050611c3081611c0a565b92915050565b600063ffffffff82169050919050565b611c4f81611c36565b8114611c5a57600080fd5b50565b600081519050611c6c81611c46565b92915050565b60008060008060808587031215611c8c57611c8b610cf5565b5b6000611c9a87828801611c21565b9450506020611cab878288016114a0565b9350506040611cbc87828801611c5d565b9250506060611ccd87828801611c21565b91505092959194509250565b600060208284031215611cef57611cee610cf5565b5b6000611cfd84828501611c21565b91505092915050565b611d0f81611b5a565b8114611d1a57600080fd5b50565b600081519050611d2c81611d06565b92915050565b600060208284031215611d4857611d47610cf5565b5b6000611d5684828501611d1d565b91505092915050565b611d688161140c565b82525050565b611d7781611b5a565b82525050565b6000606082019050611d926000830186611d5f565b611d9f6020830185611d5f565b611dac6040830184611d6e565b949350505050565b6000611dbf826110fd565b9050919050565b611dcf81611db4565b8114611dda57600080fd5b50565b600081519050611dec81611dc6565b92915050565b600060208284031215611e0857611e07610cf5565b5b6000611e1684828501611ddd565b91505092915050565b6000611e2a82610df9565b9150611e3583610df9565b9250828203905081811115611e4d57611e4c61199e565b5b92915050565b6000611e5e82610df9565b9150611e6983610df9565b9250611e967fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484611a2d565b905092915050565b6000611ea982610df9565b9150611eb483610df9565b9250828202611ec281610df9565b91508282048414831517611ed957611ed861199e565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000611f1a82610df9565b9150611f2583610df9565b925082611f3557611f34611ee0565b5b82820490509291505056fea2646970667358221220a46763ce702404ea2983f783f2c4e5f53edd899fbe2e87969ebcf94c7bb4feaf64736f6c63430008160033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c80631d20d10a1461005c5780634757efc11461008c5780634d20d0f8146100bc5780635b549182146100da578063ff514fa3146100f8575b600080fd5b61007660048036038101906100719190610d64565b610129565b6040516100839190610ec4565b60405180910390f35b6100a660048036038101906100a19190610f3c565b610328565b6040516100b391906110db565b60405180910390f35b6100c46104f3565b6040516100d1919061117c565b60405180910390f35b6100e2610517565b6040516100ef91906111b8565b60405180910390f35b610112600480360381019061010d9190611229565b61053b565b60405161012092919061137e565b60405180910390f35b606060008383905090508067ffffffffffffffff81111561014d5761014c6113ae565b5b60405190808252806020026020018201604052801561018657816020015b610173610cb2565b81526020019060019003908161016b5790505b50915060005b818110156103205760008585838181106101a9576101a86113dd565b5b90506020020160208101906101be919061145c565b90508073ffffffffffffffffffffffffffffffffffffffff16633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa15801561020b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061022f9190611580565b90919293949550909192935090919250909150905050848381518110610258576102576113dd565b5b60200260200101516000018160020b60020b815250508073ffffffffffffffffffffffffffffffffffffffff16631a6865026040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102dd919061166a565b6fffffffffffffffffffffffffffffffff16848381518110610302576103016113dd565b5b6020026020010151602001818152505050808060010191505061018c565b505092915050565b606060008383905090508067ffffffffffffffff81111561034c5761034b6113ae565b5b60405190808252806020026020018201604052801561037f57816020015b606081526020019060019003908161036a5790505b50915060005b818110156104eb576000808686848181106103a3576103a26113dd565b5b90506020020160208101906103b891906116c3565b73ffffffffffffffffffffffffffffffffffffffff167f95d89b41e2f5f391a79ec54e9d87c79d6e777c63e32c28da95b4e9e4a79250ec6040516020016103ff919061172b565b60405160208183030381529060405260405161041b919061178d565b600060405180830381855afa9150503d8060008114610456576040519150601f19603f3d011682016040523d82523d6000602084013e61045b565b606091505b50915091508161047a57604051806020016040528060008152506104be565b602081511461049c57808060200190518101906104979190611896565b6104bd565b806040516020016104ad919061178d565b6040516020818303038152906040525b5b8584815181106104d1576104d06113dd565b5b602002602001018190525050508080600101915050610385565b505092915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6060600042905060008484905090508067ffffffffffffffff811115610564576105636113ae565b5b60405190808252806020026020018201604052801561059d57816020015b61058a610ccf565b8152602001906001900390816105825790505b50925060005b81811015610607576105dc8686838181106105c1576105c06113dd565b5b9050608002018036038101906105d79190611971565b610610565b8482815181106105ef576105ee6113dd565b5b602002602001018190525080806001019150506105a3565b50509250929050565b610618610ccf565b60008061062884602001516108ae565b91509150806106385750506108a9565b60008061064886604001516108ae565b915091508061065a57505050506108a9565b600073ffffffffffffffffffffffffffffffffffffffff16866000015173ffffffffffffffffffffffffffffffffffffffff160361069b57505050506108a9565b6000806106ab886000015161099a565b91509150806106bf575050505050506108a9565b6106d28860200151896040015184610aad565b73ffffffffffffffffffffffffffffffffffffffff16886000015173ffffffffffffffffffffffffffffffffffffffff1614610713575050505050506108a9565b60006040518060a001604052808a6020015173ffffffffffffffffffffffffffffffffffffffff1681526020018a6040015173ffffffffffffffffffffffffffffffffffffffff1681526020018a60600151600a6107719190611b00565b81526020018462ffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681525090507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663c6a5026a826040518263ffffffff1660e01b81526004016107f79190611bef565b6080604051808303816000875af192505050801561083357506040513d601f19601f820116820180604052508101906108309190611c72565b60015b61086f573d8060008114610863576040519150601f19603f3d011682016040523d82523d6000602084013e610868565b606091505b50506108a1565b6108828d6060015160ff168c8b87610bdb565b8c600001818152505060018c6020019015159081151581525050505050505b505050505050505b919050565b60008060608373ffffffffffffffffffffffffffffffffffffffff167f313ce567add4d438edf58b94ff345d7d38c45b17dfc0f947988d7819dca364f96040516020016108fb919061172b565b604051602081830303815290604052604051610917919061178d565b600060405180830381855afa9150503d8060008114610952576040519150601f19603f3d011682016040523d82523d6000602084013e610957565b606091505b50809250819350505081801561096f57506000815114155b1561098f57808060200190518101906109889190611cd9565b9250610994565b600091505b50915091565b60008060608373ffffffffffffffffffffffffffffffffffffffff1663ddca3f4360e01b604051602401604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610a2e919061178d565b600060405180830381855afa9150503d8060008114610a69576040519150601f19603f3d011682016040523d82523d6000602084013e610a6e565b606091505b5080925081935050506000815103610a895760009150610aa7565b8115610aa65780806020019051810190610aa39190611d32565b92505b5b50915091565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16631698ee8260e01b878787604051602401610b0693929190611d7d565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610b70919061178d565b600060405180830381855afa9150503d8060008114610bab576040519150601f19603f3d011682016040523d82523d6000602084013e610bb0565b606091505b50915091508115610bd25780806020019051810190610bcf9190611df2565b92505b50509392505050565b6000838503610bec57819050610c45565b83851015610c1e578484610c009190611e1f565b600a610c0c9190611e53565b82610c179190611e9e565b9050610c44565b8385610c2a9190611e1f565b600a610c369190611e53565b82610c419190611f0f565b90505b5b6012830315610caa576012831115610c8257601283610c649190611e1f565b600a610c709190611e53565b81610c7b9190611f0f565b9050610ca9565b826012610c8f9190611e1f565b600a610c9b9190611e53565b81610ca69190611e9e565b90505b5b949350505050565b6040518060400160405280600060020b8152602001600081525090565b6040518060400160405280600081526020016000151581525090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b60008083601f840112610d2457610d23610cff565b5b8235905067ffffffffffffffff811115610d4157610d40610d04565b5b602083019150836020820283011115610d5d57610d5c610d09565b5b9250929050565b60008060208385031215610d7b57610d7a610cf5565b5b600083013567ffffffffffffffff811115610d9957610d98610cfa565b5b610da585828601610d0e565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60008160020b9050919050565b610df381610ddd565b82525050565b6000819050919050565b610e0c81610df9565b82525050565b604082016000820151610e286000850182610dea565b506020820151610e3b6020850182610e03565b50505050565b6000610e4d8383610e12565b60408301905092915050565b6000602082019050919050565b6000610e7182610db1565b610e7b8185610dbc565b9350610e8683610dcd565b8060005b83811015610eb7578151610e9e8882610e41565b9750610ea983610e59565b925050600181019050610e8a565b5085935050505092915050565b60006020820190508181036000830152610ede8184610e66565b905092915050565b60008083601f840112610efc57610efb610cff565b5b8235905067ffffffffffffffff811115610f1957610f18610d04565b5b602083019150836020820283011115610f3557610f34610d09565b5b9250929050565b60008060208385031215610f5357610f52610cf5565b5b600083013567ffffffffffffffff811115610f7157610f70610cfa565b5b610f7d85828601610ee6565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610fef578082015181840152602081019050610fd4565b60008484015250505050565b6000601f19601f8301169050919050565b600061101782610fb5565b6110218185610fc0565b9350611031818560208601610fd1565b61103a81610ffb565b840191505092915050565b6000611051838361100c565b905092915050565b6000602082019050919050565b600061107182610f89565b61107b8185610f94565b93508360208202850161108d85610fa5565b8060005b858110156110c957848403895281516110aa8582611045565b94506110b583611059565b925060208a01995050600181019050611091565b50829750879550505050505092915050565b600060208201905081810360008301526110f58184611066565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061114261113d611138846110fd565b61111d565b6110fd565b9050919050565b600061115482611127565b9050919050565b600061116682611149565b9050919050565b6111768161115b565b82525050565b6000602082019050611191600083018461116d565b92915050565b60006111a282611149565b9050919050565b6111b281611197565b82525050565b60006020820190506111cd60008301846111a9565b92915050565b60008083601f8401126111e9576111e8610cff565b5b8235905067ffffffffffffffff81111561120657611205610d04565b5b60208301915083608082028301111561122257611221610d09565b5b9250929050565b600080602083850312156112405761123f610cf5565b5b600083013567ffffffffffffffff81111561125e5761125d610cfa565b5b61126a858286016111d3565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60008115159050919050565b6112b7816112a2565b82525050565b6040820160008201516112d36000850182610e03565b5060208201516112e660208501826112ae565b50505050565b60006112f883836112bd565b60408301905092915050565b6000602082019050919050565b600061131c82611276565b6113268185611281565b935061133183611292565b8060005b8381101561136257815161134988826112ec565b975061135483611304565b925050600181019050611335565b5085935050505092915050565b61137881610df9565b82525050565b600060408201905081810360008301526113988185611311565b90506113a7602083018461136f565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000611417826110fd565b9050919050565b60006114298261140c565b9050919050565b6114398161141e565b811461144457600080fd5b50565b60008135905061145681611430565b92915050565b60006020828403121561147257611471610cf5565b5b600061148084828501611447565b91505092915050565b611492816110fd565b811461149d57600080fd5b50565b6000815190506114af81611489565b92915050565b6114be81610ddd565b81146114c957600080fd5b50565b6000815190506114db816114b5565b92915050565b600061ffff82169050919050565b6114f8816114e1565b811461150357600080fd5b50565b600081519050611515816114ef565b92915050565b600060ff82169050919050565b6115318161151b565b811461153c57600080fd5b50565b60008151905061154e81611528565b92915050565b61155d816112a2565b811461156857600080fd5b50565b60008151905061157a81611554565b92915050565b600080600080600080600060e0888a03121561159f5761159e610cf5565b5b60006115ad8a828b016114a0565b97505060206115be8a828b016114cc565b96505060406115cf8a828b01611506565b95505060606115e08a828b01611506565b94505060806115f18a828b01611506565b93505060a06116028a828b0161153f565b92505060c06116138a828b0161156b565b91505092959891949750929550565b60006fffffffffffffffffffffffffffffffff82169050919050565b61164781611622565b811461165257600080fd5b50565b6000815190506116648161163e565b92915050565b6000602082840312156116805761167f610cf5565b5b600061168e84828501611655565b91505092915050565b6116a08161140c565b81146116ab57600080fd5b50565b6000813590506116bd81611697565b92915050565b6000602082840312156116d9576116d8610cf5565b5b60006116e7848285016116ae565b91505092915050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b611725816116f0565b82525050565b6000602082019050611740600083018461171c565b92915050565b600081519050919050565b600081905092915050565b600061176782611746565b6117718185611751565b9350611781818560208601610fd1565b80840191505092915050565b6000611799828461175c565b915081905092915050565b600080fd5b6117b282610ffb565b810181811067ffffffffffffffff821117156117d1576117d06113ae565b5b80604052505050565b60006117e4610ceb565b90506117f082826117a9565b919050565b600067ffffffffffffffff8211156118105761180f6113ae565b5b61181982610ffb565b9050602081019050919050565b6000611839611834846117f5565b6117da565b905082815260208101848484011115611855576118546117a4565b5b611860848285610fd1565b509392505050565b600082601f83011261187d5761187c610cff565b5b815161188d848260208601611826565b91505092915050565b6000602082840312156118ac576118ab610cf5565b5b600082015167ffffffffffffffff8111156118ca576118c9610cfa565b5b6118d684828501611868565b91505092915050565b600080fd5b6000813590506118f381611528565b92915050565b60006080828403121561190f5761190e6118df565b5b61191960806117da565b9050600061192984828501611447565b600083015250602061193d848285016116ae565b6020830152506040611951848285016116ae565b6040830152506060611965848285016118e4565b60608301525092915050565b60006080828403121561198757611986610cf5565b5b6000611995848285016118f9565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008160011c9050919050565b6000808291508390505b6001851115611a2457808604811115611a00576119ff61199e565b5b6001851615611a0f5780820291505b8081029050611a1d856119cd565b94506119e4565b94509492505050565b600082611a3d5760019050611af9565b81611a4b5760009050611af9565b8160018114611a615760028114611a6b57611a9a565b6001915050611af9565b60ff841115611a7d57611a7c61199e565b5b8360020a915084821115611a9457611a9361199e565b5b50611af9565b5060208310610133831016604e8410600b8410161715611acf5782820a905083811115611aca57611ac961199e565b5b611af9565b611adc84848460016119da565b92509050818404811115611af357611af261199e565b5b81810290505b9392505050565b6000611b0b82610df9565b9150611b168361151b565b9250611b437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484611a2d565b905092915050565b611b548161140c565b82525050565b600062ffffff82169050919050565b611b7281611b5a565b82525050565b611b81816110fd565b82525050565b60a082016000820151611b9d6000850182611b4b565b506020820151611bb06020850182611b4b565b506040820151611bc36040850182610e03565b506060820151611bd66060850182611b69565b506080820151611be96080850182611b78565b50505050565b600060a082019050611c046000830184611b87565b92915050565b611c1381610df9565b8114611c1e57600080fd5b50565b600081519050611c3081611c0a565b92915050565b600063ffffffff82169050919050565b611c4f81611c36565b8114611c5a57600080fd5b50565b600081519050611c6c81611c46565b92915050565b60008060008060808587031215611c8c57611c8b610cf5565b5b6000611c9a87828801611c21565b9450506020611cab878288016114a0565b9350506040611cbc87828801611c5d565b9250506060611ccd87828801611c21565b91505092959194509250565b600060208284031215611cef57611cee610cf5565b5b6000611cfd84828501611c21565b91505092915050565b611d0f81611b5a565b8114611d1a57600080fd5b50565b600081519050611d2c81611d06565b92915050565b600060208284031215611d4857611d47610cf5565b5b6000611d5684828501611d1d565b91505092915050565b611d688161140c565b82525050565b611d7781611b5a565b82525050565b6000606082019050611d926000830186611d5f565b611d9f6020830185611d5f565b611dac6040830184611d6e565b949350505050565b6000611dbf826110fd565b9050919050565b611dcf81611db4565b8114611dda57600080fd5b50565b600081519050611dec81611dc6565b92915050565b600060208284031215611e0857611e07610cf5565b5b6000611e1684828501611ddd565b91505092915050565b6000611e2a82610df9565b9150611e3583610df9565b9250828203905081811115611e4d57611e4c61199e565b5b92915050565b6000611e5e82610df9565b9150611e6983610df9565b9250611e967fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484611a2d565b905092915050565b6000611ea982610df9565b9150611eb483610df9565b9250828202611ec281610df9565b91508282048414831517611ed957611ed861199e565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000611f1a82610df9565b9150611f2583610df9565b925082611f3557611f34611ee0565b5b82820490509291505056fea2646970667358221220a46763ce702404ea2983f783f2c4e5f53edd899fbe2e87969ebcf94c7bb4feaf64736f6c63430008160033", + "numDeployments": 3, + "solcInputHash": "95c5c63d5bf478d174b8a78c3c500ebc", + "metadata": "{\"compiler\":{\"version\":\"0.8.22+commit.4fc1097e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IUniswapV3Factory\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"contract IQuoterV2\",\"name\":\"_quoter\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contract IUniswapV3Pool\",\"name\":\"pool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"base\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"quote\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"amountInDecimals\",\"type\":\"uint8\"}],\"internalType\":\"struct UniswapV3FetcherHelper.InputData[]\",\"name\":\"_data\",\"type\":\"tuple[]\"}],\"name\":\"getPrices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"price\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"internalType\":\"struct UniswapV3FetcherHelper.Price[]\",\"name\":\"prices\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IUniswapV3Pool[]\",\"name\":\"_pools\",\"type\":\"address[]\"}],\"name\":\"liquidityData\",\"outputs\":[{\"components\":[{\"internalType\":\"uint160\",\"name\":\"sqrtPriceX96\",\"type\":\"uint160\"},{\"internalType\":\"int24\",\"name\":\"tick\",\"type\":\"int24\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"internalType\":\"struct UniswapV3FetcherHelper.LiquidityData[]\",\"name\":\"data\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_tokens\",\"type\":\"address[]\"}],\"name\":\"tokensSymbols\",\"outputs\":[{\"internalType\":\"string[]\",\"name\":\"symbols\",\"type\":\"string[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"uniswapV3Factory\",\"outputs\":[{\"internalType\":\"contract IUniswapV3Factory\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"uniswapV3Quoter\",\"outputs\":[{\"internalType\":\"contract IQuoterV2\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getPrices((address,address,address,uint8)[])\":{\"details\":\"this method will return estimations for swap for one base token it can not be view, but to get estimation you have to call it in a static way Tokens that do not have `.decimals()` are not supported\",\"params\":{\"_data\":\"array of PriceData, each PriceData can accept multiple pools per one price, price is fetched from pool, that has biggest liquidity (quote.balanceOf(pool))\"},\"returns\":{\"prices\":\"prices normalized from input amount (10 ** prices[n].amountInDecimals) to one token price\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/fetchers/uniswapV3/UniswapV3FetcherHelper.sol\":\"UniswapV3FetcherHelper\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":0},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title The interface for the Uniswap V3 Factory\\n/// @notice The Uniswap V3 Factory facilitates creation of Uniswap V3 pools and control over the protocol fees\\ninterface IUniswapV3Factory {\\n /// @notice Emitted when the owner of the factory is changed\\n /// @param oldOwner The owner before the owner was changed\\n /// @param newOwner The owner after the owner was changed\\n event OwnerChanged(address indexed oldOwner, address indexed newOwner);\\n\\n /// @notice Emitted when a pool is created\\n /// @param token0 The first token of the pool by address sort order\\n /// @param token1 The second token of the pool by address sort order\\n /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n /// @param tickSpacing The minimum number of ticks between initialized ticks\\n /// @param pool The address of the created pool\\n event PoolCreated(\\n address indexed token0,\\n address indexed token1,\\n uint24 indexed fee,\\n int24 tickSpacing,\\n address pool\\n );\\n\\n /// @notice Emitted when a new fee amount is enabled for pool creation via the factory\\n /// @param fee The enabled fee, denominated in hundredths of a bip\\n /// @param tickSpacing The minimum number of ticks between initialized ticks for pools created with the given fee\\n event FeeAmountEnabled(uint24 indexed fee, int24 indexed tickSpacing);\\n\\n /// @notice Returns the current owner of the factory\\n /// @dev Can be changed by the current owner via setOwner\\n /// @return The address of the factory owner\\n function owner() external view returns (address);\\n\\n /// @notice Returns the tick spacing for a given fee amount, if enabled, or 0 if not enabled\\n /// @dev A fee amount can never be removed, so this value should be hard coded or cached in the calling context\\n /// @param fee The enabled fee, denominated in hundredths of a bip. Returns 0 in case of unenabled fee\\n /// @return The tick spacing\\n function feeAmountTickSpacing(uint24 fee) external view returns (int24);\\n\\n /// @notice Returns the pool address for a given pair of tokens and a fee, or address 0 if it does not exist\\n /// @dev tokenA and tokenB may be passed in either token0/token1 or token1/token0 order\\n /// @param tokenA The contract address of either token0 or token1\\n /// @param tokenB The contract address of the other token\\n /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n /// @return pool The pool address\\n function getPool(\\n address tokenA,\\n address tokenB,\\n uint24 fee\\n ) external view returns (address pool);\\n\\n /// @notice Creates a pool for the given two tokens and fee\\n /// @param tokenA One of the two tokens in the desired pool\\n /// @param tokenB The other of the two tokens in the desired pool\\n /// @param fee The desired fee for the pool\\n /// @dev tokenA and tokenB may be passed in either order: token0/token1 or token1/token0. tickSpacing is retrieved\\n /// from the fee. The call will revert if the pool already exists, the fee is invalid, or the token arguments\\n /// are invalid.\\n /// @return pool The address of the newly created pool\\n function createPool(\\n address tokenA,\\n address tokenB,\\n uint24 fee\\n ) external returns (address pool);\\n\\n /// @notice Updates the owner of the factory\\n /// @dev Must be called by the current owner\\n /// @param _owner The new owner of the factory\\n function setOwner(address _owner) external;\\n\\n /// @notice Enables a fee amount with the given tickSpacing\\n /// @dev Fee amounts may never be removed once enabled\\n /// @param fee The fee amount to enable, denominated in hundredths of a bip (i.e. 1e-6)\\n /// @param tickSpacing The spacing between ticks to be enforced for all pools created with the given fee amount\\n function enableFeeAmount(uint24 fee, int24 tickSpacing) external;\\n}\\n\",\"keccak256\":\"0xcc3d0c93fc9ac0febbe09f941b465b57f750bcf3b48432da0b97dc289cfdc489\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n IUniswapV3PoolImmutables,\\n IUniswapV3PoolState,\\n IUniswapV3PoolDerivedState,\\n IUniswapV3PoolActions,\\n IUniswapV3PoolOwnerActions,\\n IUniswapV3PoolEvents\\n{\\n\\n}\\n\",\"keccak256\":\"0xfe6113d518466cd6652c85b111e01f33eb62157f49ae5ed7d5a3947a2044adb1\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Permissionless pool actions\\n/// @notice Contains pool methods that can be called by anyone\\ninterface IUniswapV3PoolActions {\\n /// @notice Sets the initial price for the pool\\n /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\\n /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\\n function initialize(uint160 sqrtPriceX96) external;\\n\\n /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\\n /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\\n /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\\n /// on tickLower, tickUpper, the amount of liquidity, and the current price.\\n /// @param recipient The address for which the liquidity will be created\\n /// @param tickLower The lower tick of the position in which to add liquidity\\n /// @param tickUpper The upper tick of the position in which to add liquidity\\n /// @param amount The amount of liquidity to mint\\n /// @param data Any data that should be passed through to the callback\\n /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\\n /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\\n function mint(\\n address recipient,\\n int24 tickLower,\\n int24 tickUpper,\\n uint128 amount,\\n bytes calldata data\\n ) external returns (uint256 amount0, uint256 amount1);\\n\\n /// @notice Collects tokens owed to a position\\n /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\\n /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\\n /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\\n /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\\n /// @param recipient The address which should receive the fees collected\\n /// @param tickLower The lower tick of the position for which to collect fees\\n /// @param tickUpper The upper tick of the position for which to collect fees\\n /// @param amount0Requested How much token0 should be withdrawn from the fees owed\\n /// @param amount1Requested How much token1 should be withdrawn from the fees owed\\n /// @return amount0 The amount of fees collected in token0\\n /// @return amount1 The amount of fees collected in token1\\n function collect(\\n address recipient,\\n int24 tickLower,\\n int24 tickUpper,\\n uint128 amount0Requested,\\n uint128 amount1Requested\\n ) external returns (uint128 amount0, uint128 amount1);\\n\\n /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\\n /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\\n /// @dev Fees must be collected separately via a call to #collect\\n /// @param tickLower The lower tick of the position for which to burn liquidity\\n /// @param tickUpper The upper tick of the position for which to burn liquidity\\n /// @param amount How much liquidity to burn\\n /// @return amount0 The amount of token0 sent to the recipient\\n /// @return amount1 The amount of token1 sent to the recipient\\n function burn(\\n int24 tickLower,\\n int24 tickUpper,\\n uint128 amount\\n ) external returns (uint256 amount0, uint256 amount1);\\n\\n /// @notice Swap token0 for token1, or token1 for token0\\n /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\\n /// @param recipient The address to receive the output of the swap\\n /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\\n /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\\n /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\\n /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\\n /// @param data Any data to be passed through to the callback\\n /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\\n /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n\\n /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\\n /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\\n /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\\n /// with 0 amount{0,1} and sending the donation amount(s) from the callback\\n /// @param recipient The address which will receive the token0 and token1 amounts\\n /// @param amount0 The amount of token0 to send\\n /// @param amount1 The amount of token1 to send\\n /// @param data Any data to be passed through to the callback\\n function flash(\\n address recipient,\\n uint256 amount0,\\n uint256 amount1,\\n bytes calldata data\\n ) external;\\n\\n /// @notice Increase the maximum number of price and liquidity observations that this pool will store\\n /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\\n /// the input observationCardinalityNext.\\n /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\\n function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;\\n}\\n\",\"keccak256\":\"0x9453dd0e7442188667d01d9b65de3f1e14e9511ff3e303179a15f6fc267f7634\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that is not stored\\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\\n/// blockchain. The functions here may have variable gas costs.\\ninterface IUniswapV3PoolDerivedState {\\n /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\\n /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\\n /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\\n /// you must call it with secondsAgos = [3600, 0].\\n /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\\n /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\\n /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\\n /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\\n /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\\n /// timestamp\\n function observe(uint32[] calldata secondsAgos)\\n external\\n view\\n returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);\\n\\n /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\\n /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\\n /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\\n /// snapshot is taken and the second snapshot is taken.\\n /// @param tickLower The lower tick of the range\\n /// @param tickUpper The upper tick of the range\\n /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\\n /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\\n /// @return secondsInside The snapshot of seconds per liquidity for the range\\n function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\\n external\\n view\\n returns (\\n int56 tickCumulativeInside,\\n uint160 secondsPerLiquidityInsideX128,\\n uint32 secondsInside\\n );\\n}\\n\",\"keccak256\":\"0xe603ac5b17ecdee73ba2b27efdf386c257a19c14206e87eee77e2017b742d9e5\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Events emitted by a pool\\n/// @notice Contains all events emitted by the pool\\ninterface IUniswapV3PoolEvents {\\n /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\\n /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\\n /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\\n /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\\n event Initialize(uint160 sqrtPriceX96, int24 tick);\\n\\n /// @notice Emitted when liquidity is minted for a given position\\n /// @param sender The address that minted the liquidity\\n /// @param owner The owner of the position and recipient of any minted liquidity\\n /// @param tickLower The lower tick of the position\\n /// @param tickUpper The upper tick of the position\\n /// @param amount The amount of liquidity minted to the position range\\n /// @param amount0 How much token0 was required for the minted liquidity\\n /// @param amount1 How much token1 was required for the minted liquidity\\n event Mint(\\n address sender,\\n address indexed owner,\\n int24 indexed tickLower,\\n int24 indexed tickUpper,\\n uint128 amount,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n /// @notice Emitted when fees are collected by the owner of a position\\n /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\\n /// @param owner The owner of the position for which fees are collected\\n /// @param tickLower The lower tick of the position\\n /// @param tickUpper The upper tick of the position\\n /// @param amount0 The amount of token0 fees collected\\n /// @param amount1 The amount of token1 fees collected\\n event Collect(\\n address indexed owner,\\n address recipient,\\n int24 indexed tickLower,\\n int24 indexed tickUpper,\\n uint128 amount0,\\n uint128 amount1\\n );\\n\\n /// @notice Emitted when a position's liquidity is removed\\n /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\\n /// @param owner The owner of the position for which liquidity is removed\\n /// @param tickLower The lower tick of the position\\n /// @param tickUpper The upper tick of the position\\n /// @param amount The amount of liquidity to remove\\n /// @param amount0 The amount of token0 withdrawn\\n /// @param amount1 The amount of token1 withdrawn\\n event Burn(\\n address indexed owner,\\n int24 indexed tickLower,\\n int24 indexed tickUpper,\\n uint128 amount,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n /// @notice Emitted by the pool for any swaps between token0 and token1\\n /// @param sender The address that initiated the swap call, and that received the callback\\n /// @param recipient The address that received the output of the swap\\n /// @param amount0 The delta of the token0 balance of the pool\\n /// @param amount1 The delta of the token1 balance of the pool\\n /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\\n /// @param liquidity The liquidity of the pool after the swap\\n /// @param tick The log base 1.0001 of price of the pool after the swap\\n event Swap(\\n address indexed sender,\\n address indexed recipient,\\n int256 amount0,\\n int256 amount1,\\n uint160 sqrtPriceX96,\\n uint128 liquidity,\\n int24 tick\\n );\\n\\n /// @notice Emitted by the pool for any flashes of token0/token1\\n /// @param sender The address that initiated the swap call, and that received the callback\\n /// @param recipient The address that received the tokens from flash\\n /// @param amount0 The amount of token0 that was flashed\\n /// @param amount1 The amount of token1 that was flashed\\n /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\\n /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\\n event Flash(\\n address indexed sender,\\n address indexed recipient,\\n uint256 amount0,\\n uint256 amount1,\\n uint256 paid0,\\n uint256 paid1\\n );\\n\\n /// @notice Emitted by the pool for increases to the number of observations that can be stored\\n /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\\n /// just before a mint/swap/burn.\\n /// @param observationCardinalityNextOld The previous value of the next observation cardinality\\n /// @param observationCardinalityNextNew The updated value of the next observation cardinality\\n event IncreaseObservationCardinalityNext(\\n uint16 observationCardinalityNextOld,\\n uint16 observationCardinalityNextNew\\n );\\n\\n /// @notice Emitted when the protocol fee is changed by the pool\\n /// @param feeProtocol0Old The previous value of the token0 protocol fee\\n /// @param feeProtocol1Old The previous value of the token1 protocol fee\\n /// @param feeProtocol0New The updated value of the token0 protocol fee\\n /// @param feeProtocol1New The updated value of the token1 protocol fee\\n event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);\\n\\n /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\\n /// @param sender The address that collects the protocol fees\\n /// @param recipient The address that receives the collected protocol fees\\n /// @param amount0 The amount of token0 protocol fees that is withdrawn\\n /// @param amount0 The amount of token1 protocol fees that is withdrawn\\n event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);\\n}\\n\",\"keccak256\":\"0x8071514d0fe5d17d6fbd31c191cdfb703031c24e0ece3621d88ab10e871375cd\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that never changes\\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\\ninterface IUniswapV3PoolImmutables {\\n /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\\n /// @return The contract address\\n function factory() external view returns (address);\\n\\n /// @notice The first of the two tokens of the pool, sorted by address\\n /// @return The token contract address\\n function token0() external view returns (address);\\n\\n /// @notice The second of the two tokens of the pool, sorted by address\\n /// @return The token contract address\\n function token1() external view returns (address);\\n\\n /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\\n /// @return The fee\\n function fee() external view returns (uint24);\\n\\n /// @notice The pool tick spacing\\n /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\\n /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\\n /// This value is an int24 to avoid casting even though it is always positive.\\n /// @return The tick spacing\\n function tickSpacing() external view returns (int24);\\n\\n /// @notice The maximum amount of position liquidity that can use any tick in the range\\n /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\\n /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\\n /// @return The max amount of liquidity per tick\\n function maxLiquidityPerTick() external view returns (uint128);\\n}\\n\",\"keccak256\":\"0xf6e5d2cd1139c4c276bdbc8e1d2b256e456c866a91f1b868da265c6d2685c3f7\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Permissioned pool actions\\n/// @notice Contains pool methods that may only be called by the factory owner\\ninterface IUniswapV3PoolOwnerActions {\\n /// @notice Set the denominator of the protocol's % share of the fees\\n /// @param feeProtocol0 new protocol fee for token0 of the pool\\n /// @param feeProtocol1 new protocol fee for token1 of the pool\\n function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\\n\\n /// @notice Collect the protocol fee accrued to the pool\\n /// @param recipient The address to which collected protocol fees should be sent\\n /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\\n /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\\n /// @return amount0 The protocol fee collected in token0\\n /// @return amount1 The protocol fee collected in token1\\n function collectProtocol(\\n address recipient,\\n uint128 amount0Requested,\\n uint128 amount1Requested\\n ) external returns (uint128 amount0, uint128 amount1);\\n}\\n\",\"keccak256\":\"0x759b78a2918af9e99e246dc3af084f654e48ef32bb4e4cb8a966aa3dcaece235\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n /// when accessed externally.\\n /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n /// boundary.\\n /// observationIndex The index of the last oracle observation that was written,\\n /// observationCardinality The current maximum number of observations stored in the pool,\\n /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n /// feeProtocol The protocol fee for both tokens of the pool.\\n /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n /// unlocked Whether the pool is currently locked to reentrancy\\n function slot0()\\n external\\n view\\n returns (\\n uint160 sqrtPriceX96,\\n int24 tick,\\n uint16 observationIndex,\\n uint16 observationCardinality,\\n uint16 observationCardinalityNext,\\n uint8 feeProtocol,\\n bool unlocked\\n );\\n\\n /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n /// @dev This value can overflow the uint256\\n function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n /// @dev This value can overflow the uint256\\n function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n /// @notice The amounts of token0 and token1 that are owed to the protocol\\n /// @dev Protocol fees will never exceed uint128 max in either token\\n function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n /// @notice The currently in range liquidity available to the pool\\n /// @dev This value has no relationship to the total liquidity across all ticks\\n function liquidity() external view returns (uint128);\\n\\n /// @notice Look up information about a specific tick in the pool\\n /// @param tick The tick to look up\\n /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n /// tick upper,\\n /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n /// a specific position.\\n function ticks(int24 tick)\\n external\\n view\\n returns (\\n uint128 liquidityGross,\\n int128 liquidityNet,\\n uint256 feeGrowthOutside0X128,\\n uint256 feeGrowthOutside1X128,\\n int56 tickCumulativeOutside,\\n uint160 secondsPerLiquidityOutsideX128,\\n uint32 secondsOutside,\\n bool initialized\\n );\\n\\n /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n /// @notice Returns the information about a position by the position's key\\n /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n /// @return _liquidity The amount of liquidity in the position,\\n /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n function positions(bytes32 key)\\n external\\n view\\n returns (\\n uint128 _liquidity,\\n uint256 feeGrowthInside0LastX128,\\n uint256 feeGrowthInside1LastX128,\\n uint128 tokensOwed0,\\n uint128 tokensOwed1\\n );\\n\\n /// @notice Returns data about a specific observation index\\n /// @param index The element of the observations array to fetch\\n /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n /// ago, rather than at a specific index in the array.\\n /// @return blockTimestamp The timestamp of the observation,\\n /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n /// Returns initialized whether the observation has been initialized and the values are safe to use\\n function observations(uint256 index)\\n external\\n view\\n returns (\\n uint32 blockTimestamp,\\n int56 tickCumulative,\\n uint160 secondsPerLiquidityCumulativeX128,\\n bool initialized\\n );\\n}\\n\",\"keccak256\":\"0x852dc1f5df7dcf7f11e7bb3eed79f0cea72ad4b25f6a9d2c35aafb48925fd49f\",\"license\":\"GPL-2.0-or-later\"},\"contracts/fetchers/CommonFetcher.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\npragma solidity ^0.8.0;\\n\\ncontract CommonFetcher {\\n uint256 internal constant _DECIMALS = 18;\\n bytes4 internal constant _DECIMALS_SELECTOR = bytes4(keccak256(\\\"decimals()\\\"));\\n\\n function _decimals(address _token) internal view virtual returns (uint256 decimals, bool success) {\\n bytes memory data;\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (success, data) = _token.staticcall(abi.encode(_DECIMALS_SELECTOR));\\n if (success && data.length != 0) decimals = abi.decode(data, (uint256));\\n else success = false;\\n }\\n\\n function _normalizeOneTokenPrice(\\n uint256 _amountInDecimals,\\n uint256 _baseDecimals,\\n uint256 _quoteDecimals,\\n uint256 _price\\n )\\n internal\\n pure\\n virtual\\n returns (uint256 normalizedPrice)\\n {\\n // normalize price from `amountInDecimals` to `oneToken`\\n if (_amountInDecimals == _baseDecimals) {\\n normalizedPrice = _price;\\n }\\n else if (_amountInDecimals < _baseDecimals) {\\n normalizedPrice = _price * (10 ** (_baseDecimals - _amountInDecimals));\\n } else {\\n normalizedPrice = _price / (10 ** (_amountInDecimals - _baseDecimals));\\n }\\n\\n // normalize price to 18 decimals\\n if (_quoteDecimals == _DECIMALS) {\\n // price OK\\n } else if (_quoteDecimals > _DECIMALS) {\\n normalizedPrice /= 10 ** (_quoteDecimals - _DECIMALS);\\n } else {\\n normalizedPrice *= 10 ** (_DECIMALS - _quoteDecimals);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x92c7c83829d8e2d5f38048903e63495f9ac6cf28b417bfff6ec6b1431845df50\",\"license\":\"UNLICENSED\"},\"contracts/fetchers/uniswapV3/UniswapV3FetcherHelper.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.22;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport {IUniswapV3Factory} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IUniswapV3PoolImmutables} from \\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\\\";\\nimport {IQuoterV2} from \\\"gitmodules/uniswap/v3-periphery/contracts/interfaces/IQuoterV2.sol\\\";\\n\\nimport {CommonFetcher} from \\\"../CommonFetcher.sol\\\";\\n\\ncontract UniswapV3FetcherHelper is CommonFetcher {\\n struct InputData {\\n IUniswapV3Pool pool;\\n address base;\\n address quote;\\n uint8 amountInDecimals;\\n }\\n\\n /// @param price is amount out (normalized to 18 decimals) returned by Uniswap pool for 1 quote token\\n struct Price {\\n uint256 price;\\n bool success;\\n }\\n\\n struct LiquidityData {\\n uint160 sqrtPriceX96;\\n int24 tick;\\n uint256 liquidity;\\n }\\n\\n bytes4 internal constant _SYMBOL_SELECTOR = bytes4(keccak256(\\\"symbol()\\\"));\\n\\n IUniswapV3Factory immutable public uniswapV3Factory;\\n IQuoterV2 immutable public uniswapV3Quoter;\\n\\n constructor(IUniswapV3Factory _factory, IQuoterV2 _quoter) {\\n uniswapV3Factory = _factory;\\n uniswapV3Quoter = _quoter;\\n }\\n\\n /// @dev this method will return estimations for swap for one base token\\n /// it can not be view, but to get estimation you have to call it in a static way\\n /// Tokens that do not have `.decimals()` are not supported\\n /// @param _data array of PriceData, each PriceData can accept multiple pools per one price, price is fetched from\\n /// pool, that has biggest liquidity (quote.balanceOf(pool))\\n /// @return prices prices normalized from input amount (10 ** prices[n].amountInDecimals) to one token price\\n function getPrices(InputData[] calldata _data)\\n external\\n virtual\\n returns (Price[] memory prices, uint256 timestamp)\\n {\\n timestamp = block.timestamp;\\n uint256 n = _data.length;\\n prices = new Price[](n);\\n\\n for (uint256 i = 0; i < n; i++) {\\n prices[i] = _getPrice(_data[i]);\\n }\\n }\\n\\n function tokensSymbols(address[] calldata _tokens) external view virtual returns (string[] memory symbols) {\\n uint256 n = _tokens.length;\\n symbols = new string[](n);\\n\\n for (uint256 i = 0; i < n; i++) {\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory data) = _tokens[i].staticcall(abi.encode(_SYMBOL_SELECTOR));\\n\\n symbols[i] = success\\n ? data.length == 32 ? string(abi.encodePacked(data)) : abi.decode(data, (string))\\n : \\\"\\\";\\n }\\n }\\n\\n function liquidityData(IUniswapV3Pool[] calldata _pools)\\n external\\n view\\n virtual\\n returns (LiquidityData[] memory data)\\n {\\n uint256 n = _pools.length;\\n data = new LiquidityData[](n);\\n\\n for (uint256 i = 0; i < n; i++) {\\n IUniswapV3Pool pool = _pools[i];\\n (data[i].sqrtPriceX96, data[i].tick,,,,,) = pool.slot0();\\n data[i].liquidity = pool.liquidity();\\n }\\n }\\n\\n function _getPrice(InputData memory _data) internal virtual returns (Price memory price) {\\n (uint256 baseDecimals, bool baseHasDecimals) = _decimals(_data.base);\\n if (!baseHasDecimals) return price;\\n\\n (uint256 quoteDecimals, bool quoteHasDecimals) = _decimals(_data.quote);\\n if (!quoteHasDecimals) return price;\\n\\n if (address(_data.pool) == address(0)) return price;\\n\\n (uint24 fee, bool success) = _getPoolFee(_data.pool);\\n if (!success) return price;\\n\\n if (address(_data.pool) != _getPool(_data.base, _data.quote, fee)) return price;\\n\\n IQuoterV2.QuoteExactInputSingleParams memory params = IQuoterV2.QuoteExactInputSingleParams({\\n tokenIn: _data.base,\\n tokenOut: _data.quote,\\n amountIn: 10 ** _data.amountInDecimals,\\n fee: fee,\\n sqrtPriceLimitX96: 0\\n });\\n\\n try uniswapV3Quoter.quoteExactInputSingle(params)\\n returns (uint256 tokenPrice, uint160, uint32, uint256)\\n {\\n price.price = _normalizeOneTokenPrice(_data.amountInDecimals, baseDecimals, quoteDecimals, tokenPrice);\\n price.success = true;\\n } catch (bytes memory) {\\n // continue;\\n }\\n }\\n\\n function _getPool(address _token0, address _token1, uint24 _fee) internal view virtual returns (address pool) {\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory data) = address(uniswapV3Factory).staticcall(\\n abi.encodeWithSelector(IUniswapV3Factory.getPool.selector, _token0, _token1, _fee)\\n );\\n\\n if (success) pool = abi.decode(data, (address));\\n }\\n\\n function _getPoolFee(IUniswapV3Pool _pool) internal view virtual returns (uint24 fee, bool success) {\\n bytes memory data;\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (success, data) = address(_pool).staticcall(abi.encodeWithSelector(IUniswapV3PoolImmutables.fee.selector));\\n\\n if (data.length == 0) {\\n success = false;\\n } else if (success) {\\n fee = abi.decode(data, (uint24));\\n }\\n }\\n}\\n\",\"keccak256\":\"0x66cbcfec8efd0cd0574ff6c6799ec924fb8f1f0fdf8e3ac9077df15943ec19d1\",\"license\":\"MIT\"},\"gitmodules/uniswap/v3-periphery/contracts/interfaces/IQuoterV2.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title QuoterV2 Interface\\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps.\\n/// @notice For each pool also tells you the number of initialized ticks crossed and the sqrt price of the pool after the swap.\\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\\ninterface IQuoterV2 {\\n /// @notice Returns the amount out received for a given exact input swap without executing the swap\\n /// @param path The path of the swap, i.e. each token pair and the pool fee\\n /// @param amountIn The amount of the first token to swap\\n /// @return amountOut The amount of the last token that would be received\\n /// @return sqrtPriceX96AfterList List of the sqrt price after the swap for each pool in the path\\n /// @return initializedTicksCrossedList List of the initialized ticks that the swap crossed for each pool in the path\\n /// @return gasEstimate The estimate of the gas that the swap consumes\\n function quoteExactInput(bytes memory path, uint256 amountIn)\\n external\\n returns (\\n uint256 amountOut,\\n uint160[] memory sqrtPriceX96AfterList,\\n uint32[] memory initializedTicksCrossedList,\\n uint256 gasEstimate\\n );\\n\\n struct QuoteExactInputSingleParams {\\n address tokenIn;\\n address tokenOut;\\n uint256 amountIn;\\n uint24 fee;\\n uint160 sqrtPriceLimitX96;\\n }\\n\\n /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\\n /// @param params The params for the quote, encoded as `QuoteExactInputSingleParams`\\n /// tokenIn The token being swapped in\\n /// tokenOut The token being swapped out\\n /// fee The fee of the token pool to consider for the pair\\n /// amountIn The desired input amount\\n /// sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n /// @return amountOut The amount of `tokenOut` that would be received\\n /// @return sqrtPriceX96After The sqrt price of the pool after the swap\\n /// @return initializedTicksCrossed The number of initialized ticks that the swap crossed\\n /// @return gasEstimate The estimate of the gas that the swap consumes\\n function quoteExactInputSingle(QuoteExactInputSingleParams memory params)\\n external\\n returns (\\n uint256 amountOut,\\n uint160 sqrtPriceX96After,\\n uint32 initializedTicksCrossed,\\n uint256 gasEstimate\\n );\\n\\n /// @notice Returns the amount in required for a given exact output swap without executing the swap\\n /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\\n /// @param amountOut The amount of the last token to receive\\n /// @return amountIn The amount of first token required to be paid\\n /// @return sqrtPriceX96AfterList List of the sqrt price after the swap for each pool in the path\\n /// @return initializedTicksCrossedList List of the initialized ticks that the swap crossed for each pool in the path\\n /// @return gasEstimate The estimate of the gas that the swap consumes\\n function quoteExactOutput(bytes memory path, uint256 amountOut)\\n external\\n returns (\\n uint256 amountIn,\\n uint160[] memory sqrtPriceX96AfterList,\\n uint32[] memory initializedTicksCrossedList,\\n uint256 gasEstimate\\n );\\n\\n struct QuoteExactOutputSingleParams {\\n address tokenIn;\\n address tokenOut;\\n uint256 amount;\\n uint24 fee;\\n uint160 sqrtPriceLimitX96;\\n }\\n\\n /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\\n /// @param params The params for the quote, encoded as `QuoteExactOutputSingleParams`\\n /// tokenIn The token being swapped in\\n /// tokenOut The token being swapped out\\n /// fee The fee of the token pool to consider for the pair\\n /// amountOut The desired output amount\\n /// sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\\n /// @return sqrtPriceX96After The sqrt price of the pool after the swap\\n /// @return initializedTicksCrossed The number of initialized ticks that the swap crossed\\n /// @return gasEstimate The estimate of the gas that the swap consumes\\n function quoteExactOutputSingle(QuoteExactOutputSingleParams memory params)\\n external\\n returns (\\n uint256 amountIn,\\n uint160 sqrtPriceX96After,\\n uint32 initializedTicksCrossed,\\n uint256 gasEstimate\\n );\\n}\\n\",\"keccak256\":\"0x7e931f0cd34811851031c4f1318f59b4a4b427a2d2e2968b8e5ed87a9f7f89d6\",\"license\":\"GPL-2.0-or-later\"}},\"version\":1}", + "bytecode": "0x60c06040523480156200001157600080fd5b50604051620021d3380380620021d383398181016040528101906200003791906200016a565b8173ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff16815250505050620001b1565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620000d982620000ac565b9050919050565b6000620000ed82620000cc565b9050919050565b620000ff81620000e0565b81146200010b57600080fd5b50565b6000815190506200011f81620000f4565b92915050565b60006200013282620000cc565b9050919050565b620001448162000125565b81146200015057600080fd5b50565b600081519050620001648162000139565b92915050565b60008060408385031215620001845762000183620000a7565b5b600062000194858286016200010e565b9250506020620001a78582860162000153565b9150509250929050565b60805160a051611fee620001e56000396000818161053d01526107e80152600081816105610152610afc0152611fee6000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80631d20d10a1461005c5780634757efc11461008c5780634d20d0f8146100bc5780635b549182146100da578063ff514fa3146100f8575b600080fd5b61007660048036038101906100719190610dc9565b610129565b6040516100839190610f6b565b60405180910390f35b6100a660048036038101906100a19190610fe3565b610370565b6040516100b39190611182565b60405180910390f35b6100c461053b565b6040516100d19190611203565b60405180910390f35b6100e261055f565b6040516100ef919061123f565b60405180910390f35b610112600480360381019061010d91906112b0565b610583565b604051610120929190611405565b60405180910390f35b606060008383905090508067ffffffffffffffff81111561014d5761014c611435565b5b60405190808252806020026020018201604052801561018657816020015b610173610cfa565b81526020019060019003908161016b5790505b50915060005b818110156103685760008585838181106101a9576101a8611464565b5b90506020020160208101906101be91906114e3565b90508073ffffffffffffffffffffffffffffffffffffffff16633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa15801561020b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061022f9190611607565b90919293509091925090915090505085848151811061025157610250611464565b5b602002602001015160000186858151811061026f5761026e611464565b5b60200260200101516020018260020b60020b8152508273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681525050508073ffffffffffffffffffffffffffffffffffffffff16631a6865026040518163ffffffff1660e01b8152600401602060405180830381865afa158015610301573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061032591906116f1565b6fffffffffffffffffffffffffffffffff1684838151811061034a57610349611464565b5b6020026020010151604001818152505050808060010191505061018c565b505092915050565b606060008383905090508067ffffffffffffffff81111561039457610393611435565b5b6040519080825280602002602001820160405280156103c757816020015b60608152602001906001900390816103b25790505b50915060005b81811015610533576000808686848181106103eb576103ea611464565b5b9050602002016020810190610400919061174a565b73ffffffffffffffffffffffffffffffffffffffff167f95d89b41e2f5f391a79ec54e9d87c79d6e777c63e32c28da95b4e9e4a79250ec60405160200161044791906117b2565b6040516020818303038152906040526040516104639190611814565b600060405180830381855afa9150503d806000811461049e576040519150601f19603f3d011682016040523d82523d6000602084013e6104a3565b606091505b5091509150816104c25760405180602001604052806000815250610506565b60208151146104e457808060200190518101906104df919061191d565b610505565b806040516020016104f59190611814565b6040516020818303038152906040525b5b85848151811061051957610518611464565b5b6020026020010181905250505080806001019150506103cd565b505092915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6060600042905060008484905090508067ffffffffffffffff8111156105ac576105ab611435565b5b6040519080825280602002602001820160405280156105e557816020015b6105d2610d34565b8152602001906001900390816105ca5790505b50925060005b8181101561064f5761062486868381811061060957610608611464565b5b90506080020180360381019061061f91906119f8565b610658565b84828151811061063757610636611464565b5b602002602001018190525080806001019150506105eb565b50509250929050565b610660610d34565b60008061067084602001516108f6565b91509150806106805750506108f1565b60008061069086604001516108f6565b91509150806106a257505050506108f1565b600073ffffffffffffffffffffffffffffffffffffffff16866000015173ffffffffffffffffffffffffffffffffffffffff16036106e357505050506108f1565b6000806106f388600001516109e2565b9150915080610707575050505050506108f1565b61071a8860200151896040015184610af5565b73ffffffffffffffffffffffffffffffffffffffff16886000015173ffffffffffffffffffffffffffffffffffffffff161461075b575050505050506108f1565b60006040518060a001604052808a6020015173ffffffffffffffffffffffffffffffffffffffff1681526020018a6040015173ffffffffffffffffffffffffffffffffffffffff1681526020018a60600151600a6107b99190611b87565b81526020018462ffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681525090507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663c6a5026a826040518263ffffffff1660e01b815260040161083f9190611c67565b6080604051808303816000875af192505050801561087b57506040513d601f19601f820116820180604052508101906108789190611cea565b60015b6108b7573d80600081146108ab576040519150601f19603f3d011682016040523d82523d6000602084013e6108b0565b606091505b50506108e9565b6108ca8d6060015160ff168c8b87610c23565b8c600001818152505060018c6020019015159081151581525050505050505b505050505050505b919050565b60008060608373ffffffffffffffffffffffffffffffffffffffff167f313ce567add4d438edf58b94ff345d7d38c45b17dfc0f947988d7819dca364f960405160200161094391906117b2565b60405160208183030381529060405260405161095f9190611814565b600060405180830381855afa9150503d806000811461099a576040519150601f19603f3d011682016040523d82523d6000602084013e61099f565b606091505b5080925081935050508180156109b757506000815114155b156109d757808060200190518101906109d09190611d51565b92506109dc565b600091505b50915091565b60008060608373ffffffffffffffffffffffffffffffffffffffff1663ddca3f4360e01b604051602401604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610a769190611814565b600060405180830381855afa9150503d8060008114610ab1576040519150601f19603f3d011682016040523d82523d6000602084013e610ab6565b606091505b5080925081935050506000815103610ad15760009150610aef565b8115610aee5780806020019051810190610aeb9190611daa565b92505b5b50915091565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16631698ee8260e01b878787604051602401610b4e93929190611df5565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610bb89190611814565b600060405180830381855afa9150503d8060008114610bf3576040519150601f19603f3d011682016040523d82523d6000602084013e610bf8565b606091505b50915091508115610c1a5780806020019051810190610c179190611e6a565b92505b50509392505050565b6000838503610c3457819050610c8d565b83851015610c66578484610c489190611e97565b600a610c549190611ecb565b82610c5f9190611f16565b9050610c8c565b8385610c729190611e97565b600a610c7e9190611ecb565b82610c899190611f87565b90505b5b6012830315610cf2576012831115610cca57601283610cac9190611e97565b600a610cb89190611ecb565b81610cc39190611f87565b9050610cf1565b826012610cd79190611e97565b600a610ce39190611ecb565b81610cee9190611f16565b90505b5b949350505050565b6040518060600160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600060020b8152602001600081525090565b6040518060400160405280600081526020016000151581525090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b60008083601f840112610d8957610d88610d64565b5b8235905067ffffffffffffffff811115610da657610da5610d69565b5b602083019150836020820283011115610dc257610dc1610d6e565b5b9250929050565b60008060208385031215610de057610ddf610d5a565b5b600083013567ffffffffffffffff811115610dfe57610dfd610d5f565b5b610e0a85828601610d73565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b610e6b81610e42565b82525050565b60008160020b9050919050565b610e8781610e71565b82525050565b6000819050919050565b610ea081610e8d565b82525050565b606082016000820151610ebc6000850182610e62565b506020820151610ecf6020850182610e7e565b506040820151610ee26040850182610e97565b50505050565b6000610ef48383610ea6565b60608301905092915050565b6000602082019050919050565b6000610f1882610e16565b610f228185610e21565b9350610f2d83610e32565b8060005b83811015610f5e578151610f458882610ee8565b9750610f5083610f00565b925050600181019050610f31565b5085935050505092915050565b60006020820190508181036000830152610f858184610f0d565b905092915050565b60008083601f840112610fa357610fa2610d64565b5b8235905067ffffffffffffffff811115610fc057610fbf610d69565b5b602083019150836020820283011115610fdc57610fdb610d6e565b5b9250929050565b60008060208385031215610ffa57610ff9610d5a565b5b600083013567ffffffffffffffff81111561101857611017610d5f565b5b61102485828601610f8d565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561109657808201518184015260208101905061107b565b60008484015250505050565b6000601f19601f8301169050919050565b60006110be8261105c565b6110c88185611067565b93506110d8818560208601611078565b6110e1816110a2565b840191505092915050565b60006110f883836110b3565b905092915050565b6000602082019050919050565b600061111882611030565b611122818561103b565b9350836020820285016111348561104c565b8060005b85811015611170578484038952815161115185826110ec565b945061115c83611100565b925060208a01995050600181019050611138565b50829750879550505050505092915050565b6000602082019050818103600083015261119c818461110d565b905092915050565b6000819050919050565b60006111c96111c46111bf84610e42565b6111a4565b610e42565b9050919050565b60006111db826111ae565b9050919050565b60006111ed826111d0565b9050919050565b6111fd816111e2565b82525050565b600060208201905061121860008301846111f4565b92915050565b6000611229826111d0565b9050919050565b6112398161121e565b82525050565b60006020820190506112546000830184611230565b92915050565b60008083601f8401126112705761126f610d64565b5b8235905067ffffffffffffffff81111561128d5761128c610d69565b5b6020830191508360808202830111156112a9576112a8610d6e565b5b9250929050565b600080602083850312156112c7576112c6610d5a565b5b600083013567ffffffffffffffff8111156112e5576112e4610d5f565b5b6112f18582860161125a565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60008115159050919050565b61133e81611329565b82525050565b60408201600082015161135a6000850182610e97565b50602082015161136d6020850182611335565b50505050565b600061137f8383611344565b60408301905092915050565b6000602082019050919050565b60006113a3826112fd565b6113ad8185611308565b93506113b883611319565b8060005b838110156113e95781516113d08882611373565b97506113db8361138b565b9250506001810190506113bc565b5085935050505092915050565b6113ff81610e8d565b82525050565b6000604082019050818103600083015261141f8185611398565b905061142e60208301846113f6565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600061149e82610e42565b9050919050565b60006114b082611493565b9050919050565b6114c0816114a5565b81146114cb57600080fd5b50565b6000813590506114dd816114b7565b92915050565b6000602082840312156114f9576114f8610d5a565b5b6000611507848285016114ce565b91505092915050565b61151981610e42565b811461152457600080fd5b50565b60008151905061153681611510565b92915050565b61154581610e71565b811461155057600080fd5b50565b6000815190506115628161153c565b92915050565b600061ffff82169050919050565b61157f81611568565b811461158a57600080fd5b50565b60008151905061159c81611576565b92915050565b600060ff82169050919050565b6115b8816115a2565b81146115c357600080fd5b50565b6000815190506115d5816115af565b92915050565b6115e481611329565b81146115ef57600080fd5b50565b600081519050611601816115db565b92915050565b600080600080600080600060e0888a03121561162657611625610d5a565b5b60006116348a828b01611527565b97505060206116458a828b01611553565b96505060406116568a828b0161158d565b95505060606116678a828b0161158d565b94505060806116788a828b0161158d565b93505060a06116898a828b016115c6565b92505060c061169a8a828b016115f2565b91505092959891949750929550565b60006fffffffffffffffffffffffffffffffff82169050919050565b6116ce816116a9565b81146116d957600080fd5b50565b6000815190506116eb816116c5565b92915050565b60006020828403121561170757611706610d5a565b5b6000611715848285016116dc565b91505092915050565b61172781611493565b811461173257600080fd5b50565b6000813590506117448161171e565b92915050565b6000602082840312156117605761175f610d5a565b5b600061176e84828501611735565b91505092915050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6117ac81611777565b82525050565b60006020820190506117c760008301846117a3565b92915050565b600081519050919050565b600081905092915050565b60006117ee826117cd565b6117f881856117d8565b9350611808818560208601611078565b80840191505092915050565b600061182082846117e3565b915081905092915050565b600080fd5b611839826110a2565b810181811067ffffffffffffffff8211171561185857611857611435565b5b80604052505050565b600061186b610d50565b90506118778282611830565b919050565b600067ffffffffffffffff82111561189757611896611435565b5b6118a0826110a2565b9050602081019050919050565b60006118c06118bb8461187c565b611861565b9050828152602081018484840111156118dc576118db61182b565b5b6118e7848285611078565b509392505050565b600082601f83011261190457611903610d64565b5b81516119148482602086016118ad565b91505092915050565b60006020828403121561193357611932610d5a565b5b600082015167ffffffffffffffff81111561195157611950610d5f565b5b61195d848285016118ef565b91505092915050565b600080fd5b60008135905061197a816115af565b92915050565b60006080828403121561199657611995611966565b5b6119a06080611861565b905060006119b0848285016114ce565b60008301525060206119c484828501611735565b60208301525060406119d884828501611735565b60408301525060606119ec8482850161196b565b60608301525092915050565b600060808284031215611a0e57611a0d610d5a565b5b6000611a1c84828501611980565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008160011c9050919050565b6000808291508390505b6001851115611aab57808604811115611a8757611a86611a25565b5b6001851615611a965780820291505b8081029050611aa485611a54565b9450611a6b565b94509492505050565b600082611ac45760019050611b80565b81611ad25760009050611b80565b8160018114611ae85760028114611af257611b21565b6001915050611b80565b60ff841115611b0457611b03611a25565b5b8360020a915084821115611b1b57611b1a611a25565b5b50611b80565b5060208310610133831016604e8410600b8410161715611b565782820a905083811115611b5157611b50611a25565b5b611b80565b611b638484846001611a61565b92509050818404811115611b7a57611b79611a25565b5b81810290505b9392505050565b6000611b9282610e8d565b9150611b9d836115a2565b9250611bca7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484611ab4565b905092915050565b611bdb81611493565b82525050565b600062ffffff82169050919050565b611bf981611be1565b82525050565b60a082016000820151611c156000850182611bd2565b506020820151611c286020850182611bd2565b506040820151611c3b6040850182610e97565b506060820151611c4e6060850182611bf0565b506080820151611c616080850182610e62565b50505050565b600060a082019050611c7c6000830184611bff565b92915050565b611c8b81610e8d565b8114611c9657600080fd5b50565b600081519050611ca881611c82565b92915050565b600063ffffffff82169050919050565b611cc781611cae565b8114611cd257600080fd5b50565b600081519050611ce481611cbe565b92915050565b60008060008060808587031215611d0457611d03610d5a565b5b6000611d1287828801611c99565b9450506020611d2387828801611527565b9350506040611d3487828801611cd5565b9250506060611d4587828801611c99565b91505092959194509250565b600060208284031215611d6757611d66610d5a565b5b6000611d7584828501611c99565b91505092915050565b611d8781611be1565b8114611d9257600080fd5b50565b600081519050611da481611d7e565b92915050565b600060208284031215611dc057611dbf610d5a565b5b6000611dce84828501611d95565b91505092915050565b611de081611493565b82525050565b611def81611be1565b82525050565b6000606082019050611e0a6000830186611dd7565b611e176020830185611dd7565b611e246040830184611de6565b949350505050565b6000611e3782610e42565b9050919050565b611e4781611e2c565b8114611e5257600080fd5b50565b600081519050611e6481611e3e565b92915050565b600060208284031215611e8057611e7f610d5a565b5b6000611e8e84828501611e55565b91505092915050565b6000611ea282610e8d565b9150611ead83610e8d565b9250828203905081811115611ec557611ec4611a25565b5b92915050565b6000611ed682610e8d565b9150611ee183610e8d565b9250611f0e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484611ab4565b905092915050565b6000611f2182610e8d565b9150611f2c83610e8d565b9250828202611f3a81610e8d565b91508282048414831517611f5157611f50611a25565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000611f9282610e8d565b9150611f9d83610e8d565b925082611fad57611fac611f58565b5b82820490509291505056fea2646970667358221220d8b96c068c43f2d96b2b745c57189244d3c23b76c76c71618274b8cb58f1ef9264736f6c63430008160033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c80631d20d10a1461005c5780634757efc11461008c5780634d20d0f8146100bc5780635b549182146100da578063ff514fa3146100f8575b600080fd5b61007660048036038101906100719190610dc9565b610129565b6040516100839190610f6b565b60405180910390f35b6100a660048036038101906100a19190610fe3565b610370565b6040516100b39190611182565b60405180910390f35b6100c461053b565b6040516100d19190611203565b60405180910390f35b6100e261055f565b6040516100ef919061123f565b60405180910390f35b610112600480360381019061010d91906112b0565b610583565b604051610120929190611405565b60405180910390f35b606060008383905090508067ffffffffffffffff81111561014d5761014c611435565b5b60405190808252806020026020018201604052801561018657816020015b610173610cfa565b81526020019060019003908161016b5790505b50915060005b818110156103685760008585838181106101a9576101a8611464565b5b90506020020160208101906101be91906114e3565b90508073ffffffffffffffffffffffffffffffffffffffff16633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa15801561020b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061022f9190611607565b90919293509091925090915090505085848151811061025157610250611464565b5b602002602001015160000186858151811061026f5761026e611464565b5b60200260200101516020018260020b60020b8152508273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681525050508073ffffffffffffffffffffffffffffffffffffffff16631a6865026040518163ffffffff1660e01b8152600401602060405180830381865afa158015610301573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061032591906116f1565b6fffffffffffffffffffffffffffffffff1684838151811061034a57610349611464565b5b6020026020010151604001818152505050808060010191505061018c565b505092915050565b606060008383905090508067ffffffffffffffff81111561039457610393611435565b5b6040519080825280602002602001820160405280156103c757816020015b60608152602001906001900390816103b25790505b50915060005b81811015610533576000808686848181106103eb576103ea611464565b5b9050602002016020810190610400919061174a565b73ffffffffffffffffffffffffffffffffffffffff167f95d89b41e2f5f391a79ec54e9d87c79d6e777c63e32c28da95b4e9e4a79250ec60405160200161044791906117b2565b6040516020818303038152906040526040516104639190611814565b600060405180830381855afa9150503d806000811461049e576040519150601f19603f3d011682016040523d82523d6000602084013e6104a3565b606091505b5091509150816104c25760405180602001604052806000815250610506565b60208151146104e457808060200190518101906104df919061191d565b610505565b806040516020016104f59190611814565b6040516020818303038152906040525b5b85848151811061051957610518611464565b5b6020026020010181905250505080806001019150506103cd565b505092915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6060600042905060008484905090508067ffffffffffffffff8111156105ac576105ab611435565b5b6040519080825280602002602001820160405280156105e557816020015b6105d2610d34565b8152602001906001900390816105ca5790505b50925060005b8181101561064f5761062486868381811061060957610608611464565b5b90506080020180360381019061061f91906119f8565b610658565b84828151811061063757610636611464565b5b602002602001018190525080806001019150506105eb565b50509250929050565b610660610d34565b60008061067084602001516108f6565b91509150806106805750506108f1565b60008061069086604001516108f6565b91509150806106a257505050506108f1565b600073ffffffffffffffffffffffffffffffffffffffff16866000015173ffffffffffffffffffffffffffffffffffffffff16036106e357505050506108f1565b6000806106f388600001516109e2565b9150915080610707575050505050506108f1565b61071a8860200151896040015184610af5565b73ffffffffffffffffffffffffffffffffffffffff16886000015173ffffffffffffffffffffffffffffffffffffffff161461075b575050505050506108f1565b60006040518060a001604052808a6020015173ffffffffffffffffffffffffffffffffffffffff1681526020018a6040015173ffffffffffffffffffffffffffffffffffffffff1681526020018a60600151600a6107b99190611b87565b81526020018462ffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681525090507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663c6a5026a826040518263ffffffff1660e01b815260040161083f9190611c67565b6080604051808303816000875af192505050801561087b57506040513d601f19601f820116820180604052508101906108789190611cea565b60015b6108b7573d80600081146108ab576040519150601f19603f3d011682016040523d82523d6000602084013e6108b0565b606091505b50506108e9565b6108ca8d6060015160ff168c8b87610c23565b8c600001818152505060018c6020019015159081151581525050505050505b505050505050505b919050565b60008060608373ffffffffffffffffffffffffffffffffffffffff167f313ce567add4d438edf58b94ff345d7d38c45b17dfc0f947988d7819dca364f960405160200161094391906117b2565b60405160208183030381529060405260405161095f9190611814565b600060405180830381855afa9150503d806000811461099a576040519150601f19603f3d011682016040523d82523d6000602084013e61099f565b606091505b5080925081935050508180156109b757506000815114155b156109d757808060200190518101906109d09190611d51565b92506109dc565b600091505b50915091565b60008060608373ffffffffffffffffffffffffffffffffffffffff1663ddca3f4360e01b604051602401604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610a769190611814565b600060405180830381855afa9150503d8060008114610ab1576040519150601f19603f3d011682016040523d82523d6000602084013e610ab6565b606091505b5080925081935050506000815103610ad15760009150610aef565b8115610aee5780806020019051810190610aeb9190611daa565b92505b5b50915091565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16631698ee8260e01b878787604051602401610b4e93929190611df5565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610bb89190611814565b600060405180830381855afa9150503d8060008114610bf3576040519150601f19603f3d011682016040523d82523d6000602084013e610bf8565b606091505b50915091508115610c1a5780806020019051810190610c179190611e6a565b92505b50509392505050565b6000838503610c3457819050610c8d565b83851015610c66578484610c489190611e97565b600a610c549190611ecb565b82610c5f9190611f16565b9050610c8c565b8385610c729190611e97565b600a610c7e9190611ecb565b82610c899190611f87565b90505b5b6012830315610cf2576012831115610cca57601283610cac9190611e97565b600a610cb89190611ecb565b81610cc39190611f87565b9050610cf1565b826012610cd79190611e97565b600a610ce39190611ecb565b81610cee9190611f16565b90505b5b949350505050565b6040518060600160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600060020b8152602001600081525090565b6040518060400160405280600081526020016000151581525090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b60008083601f840112610d8957610d88610d64565b5b8235905067ffffffffffffffff811115610da657610da5610d69565b5b602083019150836020820283011115610dc257610dc1610d6e565b5b9250929050565b60008060208385031215610de057610ddf610d5a565b5b600083013567ffffffffffffffff811115610dfe57610dfd610d5f565b5b610e0a85828601610d73565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b610e6b81610e42565b82525050565b60008160020b9050919050565b610e8781610e71565b82525050565b6000819050919050565b610ea081610e8d565b82525050565b606082016000820151610ebc6000850182610e62565b506020820151610ecf6020850182610e7e565b506040820151610ee26040850182610e97565b50505050565b6000610ef48383610ea6565b60608301905092915050565b6000602082019050919050565b6000610f1882610e16565b610f228185610e21565b9350610f2d83610e32565b8060005b83811015610f5e578151610f458882610ee8565b9750610f5083610f00565b925050600181019050610f31565b5085935050505092915050565b60006020820190508181036000830152610f858184610f0d565b905092915050565b60008083601f840112610fa357610fa2610d64565b5b8235905067ffffffffffffffff811115610fc057610fbf610d69565b5b602083019150836020820283011115610fdc57610fdb610d6e565b5b9250929050565b60008060208385031215610ffa57610ff9610d5a565b5b600083013567ffffffffffffffff81111561101857611017610d5f565b5b61102485828601610f8d565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561109657808201518184015260208101905061107b565b60008484015250505050565b6000601f19601f8301169050919050565b60006110be8261105c565b6110c88185611067565b93506110d8818560208601611078565b6110e1816110a2565b840191505092915050565b60006110f883836110b3565b905092915050565b6000602082019050919050565b600061111882611030565b611122818561103b565b9350836020820285016111348561104c565b8060005b85811015611170578484038952815161115185826110ec565b945061115c83611100565b925060208a01995050600181019050611138565b50829750879550505050505092915050565b6000602082019050818103600083015261119c818461110d565b905092915050565b6000819050919050565b60006111c96111c46111bf84610e42565b6111a4565b610e42565b9050919050565b60006111db826111ae565b9050919050565b60006111ed826111d0565b9050919050565b6111fd816111e2565b82525050565b600060208201905061121860008301846111f4565b92915050565b6000611229826111d0565b9050919050565b6112398161121e565b82525050565b60006020820190506112546000830184611230565b92915050565b60008083601f8401126112705761126f610d64565b5b8235905067ffffffffffffffff81111561128d5761128c610d69565b5b6020830191508360808202830111156112a9576112a8610d6e565b5b9250929050565b600080602083850312156112c7576112c6610d5a565b5b600083013567ffffffffffffffff8111156112e5576112e4610d5f565b5b6112f18582860161125a565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60008115159050919050565b61133e81611329565b82525050565b60408201600082015161135a6000850182610e97565b50602082015161136d6020850182611335565b50505050565b600061137f8383611344565b60408301905092915050565b6000602082019050919050565b60006113a3826112fd565b6113ad8185611308565b93506113b883611319565b8060005b838110156113e95781516113d08882611373565b97506113db8361138b565b9250506001810190506113bc565b5085935050505092915050565b6113ff81610e8d565b82525050565b6000604082019050818103600083015261141f8185611398565b905061142e60208301846113f6565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600061149e82610e42565b9050919050565b60006114b082611493565b9050919050565b6114c0816114a5565b81146114cb57600080fd5b50565b6000813590506114dd816114b7565b92915050565b6000602082840312156114f9576114f8610d5a565b5b6000611507848285016114ce565b91505092915050565b61151981610e42565b811461152457600080fd5b50565b60008151905061153681611510565b92915050565b61154581610e71565b811461155057600080fd5b50565b6000815190506115628161153c565b92915050565b600061ffff82169050919050565b61157f81611568565b811461158a57600080fd5b50565b60008151905061159c81611576565b92915050565b600060ff82169050919050565b6115b8816115a2565b81146115c357600080fd5b50565b6000815190506115d5816115af565b92915050565b6115e481611329565b81146115ef57600080fd5b50565b600081519050611601816115db565b92915050565b600080600080600080600060e0888a03121561162657611625610d5a565b5b60006116348a828b01611527565b97505060206116458a828b01611553565b96505060406116568a828b0161158d565b95505060606116678a828b0161158d565b94505060806116788a828b0161158d565b93505060a06116898a828b016115c6565b92505060c061169a8a828b016115f2565b91505092959891949750929550565b60006fffffffffffffffffffffffffffffffff82169050919050565b6116ce816116a9565b81146116d957600080fd5b50565b6000815190506116eb816116c5565b92915050565b60006020828403121561170757611706610d5a565b5b6000611715848285016116dc565b91505092915050565b61172781611493565b811461173257600080fd5b50565b6000813590506117448161171e565b92915050565b6000602082840312156117605761175f610d5a565b5b600061176e84828501611735565b91505092915050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6117ac81611777565b82525050565b60006020820190506117c760008301846117a3565b92915050565b600081519050919050565b600081905092915050565b60006117ee826117cd565b6117f881856117d8565b9350611808818560208601611078565b80840191505092915050565b600061182082846117e3565b915081905092915050565b600080fd5b611839826110a2565b810181811067ffffffffffffffff8211171561185857611857611435565b5b80604052505050565b600061186b610d50565b90506118778282611830565b919050565b600067ffffffffffffffff82111561189757611896611435565b5b6118a0826110a2565b9050602081019050919050565b60006118c06118bb8461187c565b611861565b9050828152602081018484840111156118dc576118db61182b565b5b6118e7848285611078565b509392505050565b600082601f83011261190457611903610d64565b5b81516119148482602086016118ad565b91505092915050565b60006020828403121561193357611932610d5a565b5b600082015167ffffffffffffffff81111561195157611950610d5f565b5b61195d848285016118ef565b91505092915050565b600080fd5b60008135905061197a816115af565b92915050565b60006080828403121561199657611995611966565b5b6119a06080611861565b905060006119b0848285016114ce565b60008301525060206119c484828501611735565b60208301525060406119d884828501611735565b60408301525060606119ec8482850161196b565b60608301525092915050565b600060808284031215611a0e57611a0d610d5a565b5b6000611a1c84828501611980565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008160011c9050919050565b6000808291508390505b6001851115611aab57808604811115611a8757611a86611a25565b5b6001851615611a965780820291505b8081029050611aa485611a54565b9450611a6b565b94509492505050565b600082611ac45760019050611b80565b81611ad25760009050611b80565b8160018114611ae85760028114611af257611b21565b6001915050611b80565b60ff841115611b0457611b03611a25565b5b8360020a915084821115611b1b57611b1a611a25565b5b50611b80565b5060208310610133831016604e8410600b8410161715611b565782820a905083811115611b5157611b50611a25565b5b611b80565b611b638484846001611a61565b92509050818404811115611b7a57611b79611a25565b5b81810290505b9392505050565b6000611b9282610e8d565b9150611b9d836115a2565b9250611bca7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484611ab4565b905092915050565b611bdb81611493565b82525050565b600062ffffff82169050919050565b611bf981611be1565b82525050565b60a082016000820151611c156000850182611bd2565b506020820151611c286020850182611bd2565b506040820151611c3b6040850182610e97565b506060820151611c4e6060850182611bf0565b506080820151611c616080850182610e62565b50505050565b600060a082019050611c7c6000830184611bff565b92915050565b611c8b81610e8d565b8114611c9657600080fd5b50565b600081519050611ca881611c82565b92915050565b600063ffffffff82169050919050565b611cc781611cae565b8114611cd257600080fd5b50565b600081519050611ce481611cbe565b92915050565b60008060008060808587031215611d0457611d03610d5a565b5b6000611d1287828801611c99565b9450506020611d2387828801611527565b9350506040611d3487828801611cd5565b9250506060611d4587828801611c99565b91505092959194509250565b600060208284031215611d6757611d66610d5a565b5b6000611d7584828501611c99565b91505092915050565b611d8781611be1565b8114611d9257600080fd5b50565b600081519050611da481611d7e565b92915050565b600060208284031215611dc057611dbf610d5a565b5b6000611dce84828501611d95565b91505092915050565b611de081611493565b82525050565b611def81611be1565b82525050565b6000606082019050611e0a6000830186611dd7565b611e176020830185611dd7565b611e246040830184611de6565b949350505050565b6000611e3782610e42565b9050919050565b611e4781611e2c565b8114611e5257600080fd5b50565b600081519050611e6481611e3e565b92915050565b600060208284031215611e8057611e7f610d5a565b5b6000611e8e84828501611e55565b91505092915050565b6000611ea282610e8d565b9150611ead83610e8d565b9250828203905081811115611ec557611ec4611a25565b5b92915050565b6000611ed682610e8d565b9150611ee183610e8d565b9250611f0e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484611ab4565b905092915050565b6000611f2182610e8d565b9150611f2c83610e8d565b9250828202611f3a81610e8d565b91508282048414831517611f5157611f50611a25565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000611f9282610e8d565b9150611f9d83610e8d565b925082611fad57611fac611f58565b5b82820490509291505056fea2646970667358221220d8b96c068c43f2d96b2b745c57189244d3c23b76c76c71618274b8cb58f1ef9264736f6c63430008160033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/eth_production/solcInputs/95c5c63d5bf478d174b8a78c3c500ebc.json b/deployments/eth_production/solcInputs/95c5c63d5bf478d174b8a78c3c500ebc.json new file mode 100644 index 00000000..eb15bb46 --- /dev/null +++ b/deployments/eth_production/solcInputs/95c5c63d5bf478d174b8a78c3c500ebc.json @@ -0,0 +1,114 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n }\n _balances[to] += amount;\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n _balances[account] += amount;\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n }\n _totalSupply -= amount;\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Trees proofs.\n *\n * The proofs can be generated using the JavaScript library\n * https://github.com/miguelmota/merkletreejs[merkletreejs].\n * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.\n *\n * See `test/utils/cryptography/MerkleProof.test.js` for some examples.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(\n bytes32[] memory proof,\n bytes32 root,\n bytes32 leaf\n ) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n bytes32 proofElement = proof[i];\n if (computedHash <= proofElement) {\n // Hash(current computed hash + current element of the proof)\n computedHash = _efficientHash(computedHash, proofElement);\n } else {\n // Hash(current element of the proof + current computed hash)\n computedHash = _efficientHash(proofElement, computedHash);\n }\n }\n return computedHash;\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "@umb-network/toolbox/dist/contracts/lib/ValueDecoder.sol": { + "content": "//SPDX-License-Identifier: Unlicensed\npragma solidity >=0.6.8;\n\nlibrary ValueDecoder {\n function toUint(bytes memory _bytes) internal pure returns (uint256 value) {\n assembly {\n value := mload(add(_bytes, 32))\n }\n }\n\n function toUint(bytes32 _bytes) internal pure returns (uint256 value) {\n assembly {\n value := _bytes\n }\n }\n\n function toInt(uint224 u) internal pure returns (int256) {\n int224 i;\n uint224 max = type(uint224).max;\n\n if (u <= (max - 1) / 2) { // positive values\n assembly {\n i := add(u, 0)\n }\n\n return i;\n } else { // negative values\n assembly {\n i := sub(sub(u, max), 1)\n }\n }\n\n return i;\n }\n}\n\n" + }, + "@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Callback for IUniswapV3PoolActions#swap\n/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface\ninterface IUniswapV3SwapCallback {\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external;\n}\n" + }, + "@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title The interface for the Uniswap V3 Factory\n/// @notice The Uniswap V3 Factory facilitates creation of Uniswap V3 pools and control over the protocol fees\ninterface IUniswapV3Factory {\n /// @notice Emitted when the owner of the factory is changed\n /// @param oldOwner The owner before the owner was changed\n /// @param newOwner The owner after the owner was changed\n event OwnerChanged(address indexed oldOwner, address indexed newOwner);\n\n /// @notice Emitted when a pool is created\n /// @param token0 The first token of the pool by address sort order\n /// @param token1 The second token of the pool by address sort order\n /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\n /// @param tickSpacing The minimum number of ticks between initialized ticks\n /// @param pool The address of the created pool\n event PoolCreated(\n address indexed token0,\n address indexed token1,\n uint24 indexed fee,\n int24 tickSpacing,\n address pool\n );\n\n /// @notice Emitted when a new fee amount is enabled for pool creation via the factory\n /// @param fee The enabled fee, denominated in hundredths of a bip\n /// @param tickSpacing The minimum number of ticks between initialized ticks for pools created with the given fee\n event FeeAmountEnabled(uint24 indexed fee, int24 indexed tickSpacing);\n\n /// @notice Returns the current owner of the factory\n /// @dev Can be changed by the current owner via setOwner\n /// @return The address of the factory owner\n function owner() external view returns (address);\n\n /// @notice Returns the tick spacing for a given fee amount, if enabled, or 0 if not enabled\n /// @dev A fee amount can never be removed, so this value should be hard coded or cached in the calling context\n /// @param fee The enabled fee, denominated in hundredths of a bip. Returns 0 in case of unenabled fee\n /// @return The tick spacing\n function feeAmountTickSpacing(uint24 fee) external view returns (int24);\n\n /// @notice Returns the pool address for a given pair of tokens and a fee, or address 0 if it does not exist\n /// @dev tokenA and tokenB may be passed in either token0/token1 or token1/token0 order\n /// @param tokenA The contract address of either token0 or token1\n /// @param tokenB The contract address of the other token\n /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\n /// @return pool The pool address\n function getPool(\n address tokenA,\n address tokenB,\n uint24 fee\n ) external view returns (address pool);\n\n /// @notice Creates a pool for the given two tokens and fee\n /// @param tokenA One of the two tokens in the desired pool\n /// @param tokenB The other of the two tokens in the desired pool\n /// @param fee The desired fee for the pool\n /// @dev tokenA and tokenB may be passed in either order: token0/token1 or token1/token0. tickSpacing is retrieved\n /// from the fee. The call will revert if the pool already exists, the fee is invalid, or the token arguments\n /// are invalid.\n /// @return pool The address of the newly created pool\n function createPool(\n address tokenA,\n address tokenB,\n uint24 fee\n ) external returns (address pool);\n\n /// @notice Updates the owner of the factory\n /// @dev Must be called by the current owner\n /// @param _owner The new owner of the factory\n function setOwner(address _owner) external;\n\n /// @notice Enables a fee amount with the given tickSpacing\n /// @dev Fee amounts may never be removed once enabled\n /// @param fee The fee amount to enable, denominated in hundredths of a bip (i.e. 1e-6)\n /// @param tickSpacing The spacing between ticks to be enforced for all pools created with the given fee amount\n function enableFeeAmount(uint24 fee, int24 tickSpacing) external;\n}\n" + }, + "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport './pool/IUniswapV3PoolImmutables.sol';\nimport './pool/IUniswapV3PoolState.sol';\nimport './pool/IUniswapV3PoolDerivedState.sol';\nimport './pool/IUniswapV3PoolActions.sol';\nimport './pool/IUniswapV3PoolOwnerActions.sol';\nimport './pool/IUniswapV3PoolEvents.sol';\n\n/// @title The interface for a Uniswap V3 Pool\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\n/// to the ERC20 specification\n/// @dev The pool interface is broken up into many smaller pieces\ninterface IUniswapV3Pool is\n IUniswapV3PoolImmutables,\n IUniswapV3PoolState,\n IUniswapV3PoolDerivedState,\n IUniswapV3PoolActions,\n IUniswapV3PoolOwnerActions,\n IUniswapV3PoolEvents\n{\n\n}\n" + }, + "@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Permissionless pool actions\n/// @notice Contains pool methods that can be called by anyone\ninterface IUniswapV3PoolActions {\n /// @notice Sets the initial price for the pool\n /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\n /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\n function initialize(uint160 sqrtPriceX96) external;\n\n /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\n /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\n /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\n /// on tickLower, tickUpper, the amount of liquidity, and the current price.\n /// @param recipient The address for which the liquidity will be created\n /// @param tickLower The lower tick of the position in which to add liquidity\n /// @param tickUpper The upper tick of the position in which to add liquidity\n /// @param amount The amount of liquidity to mint\n /// @param data Any data that should be passed through to the callback\n /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\n /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\n function mint(\n address recipient,\n int24 tickLower,\n int24 tickUpper,\n uint128 amount,\n bytes calldata data\n ) external returns (uint256 amount0, uint256 amount1);\n\n /// @notice Collects tokens owed to a position\n /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\n /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\n /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\n /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\n /// @param recipient The address which should receive the fees collected\n /// @param tickLower The lower tick of the position for which to collect fees\n /// @param tickUpper The upper tick of the position for which to collect fees\n /// @param amount0Requested How much token0 should be withdrawn from the fees owed\n /// @param amount1Requested How much token1 should be withdrawn from the fees owed\n /// @return amount0 The amount of fees collected in token0\n /// @return amount1 The amount of fees collected in token1\n function collect(\n address recipient,\n int24 tickLower,\n int24 tickUpper,\n uint128 amount0Requested,\n uint128 amount1Requested\n ) external returns (uint128 amount0, uint128 amount1);\n\n /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\n /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\n /// @dev Fees must be collected separately via a call to #collect\n /// @param tickLower The lower tick of the position for which to burn liquidity\n /// @param tickUpper The upper tick of the position for which to burn liquidity\n /// @param amount How much liquidity to burn\n /// @return amount0 The amount of token0 sent to the recipient\n /// @return amount1 The amount of token1 sent to the recipient\n function burn(\n int24 tickLower,\n int24 tickUpper,\n uint128 amount\n ) external returns (uint256 amount0, uint256 amount1);\n\n /// @notice Swap token0 for token1, or token1 for token0\n /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\n /// @param recipient The address to receive the output of the swap\n /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\n /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\n /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\n /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\n /// @param data Any data to be passed through to the callback\n /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\n /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n\n /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\n /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\n /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\n /// with 0 amount{0,1} and sending the donation amount(s) from the callback\n /// @param recipient The address which will receive the token0 and token1 amounts\n /// @param amount0 The amount of token0 to send\n /// @param amount1 The amount of token1 to send\n /// @param data Any data to be passed through to the callback\n function flash(\n address recipient,\n uint256 amount0,\n uint256 amount1,\n bytes calldata data\n ) external;\n\n /// @notice Increase the maximum number of price and liquidity observations that this pool will store\n /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\n /// the input observationCardinalityNext.\n /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\n function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;\n}\n" + }, + "@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Pool state that is not stored\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\n/// blockchain. The functions here may have variable gas costs.\ninterface IUniswapV3PoolDerivedState {\n /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\n /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\n /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\n /// you must call it with secondsAgos = [3600, 0].\n /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\n /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\n /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\n /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\n /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\n /// timestamp\n function observe(uint32[] calldata secondsAgos)\n external\n view\n returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);\n\n /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\n /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\n /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\n /// snapshot is taken and the second snapshot is taken.\n /// @param tickLower The lower tick of the range\n /// @param tickUpper The upper tick of the range\n /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\n /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\n /// @return secondsInside The snapshot of seconds per liquidity for the range\n function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\n external\n view\n returns (\n int56 tickCumulativeInside,\n uint160 secondsPerLiquidityInsideX128,\n uint32 secondsInside\n );\n}\n" + }, + "@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Events emitted by a pool\n/// @notice Contains all events emitted by the pool\ninterface IUniswapV3PoolEvents {\n /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\n /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\n /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\n /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\n event Initialize(uint160 sqrtPriceX96, int24 tick);\n\n /// @notice Emitted when liquidity is minted for a given position\n /// @param sender The address that minted the liquidity\n /// @param owner The owner of the position and recipient of any minted liquidity\n /// @param tickLower The lower tick of the position\n /// @param tickUpper The upper tick of the position\n /// @param amount The amount of liquidity minted to the position range\n /// @param amount0 How much token0 was required for the minted liquidity\n /// @param amount1 How much token1 was required for the minted liquidity\n event Mint(\n address sender,\n address indexed owner,\n int24 indexed tickLower,\n int24 indexed tickUpper,\n uint128 amount,\n uint256 amount0,\n uint256 amount1\n );\n\n /// @notice Emitted when fees are collected by the owner of a position\n /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\n /// @param owner The owner of the position for which fees are collected\n /// @param tickLower The lower tick of the position\n /// @param tickUpper The upper tick of the position\n /// @param amount0 The amount of token0 fees collected\n /// @param amount1 The amount of token1 fees collected\n event Collect(\n address indexed owner,\n address recipient,\n int24 indexed tickLower,\n int24 indexed tickUpper,\n uint128 amount0,\n uint128 amount1\n );\n\n /// @notice Emitted when a position's liquidity is removed\n /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\n /// @param owner The owner of the position for which liquidity is removed\n /// @param tickLower The lower tick of the position\n /// @param tickUpper The upper tick of the position\n /// @param amount The amount of liquidity to remove\n /// @param amount0 The amount of token0 withdrawn\n /// @param amount1 The amount of token1 withdrawn\n event Burn(\n address indexed owner,\n int24 indexed tickLower,\n int24 indexed tickUpper,\n uint128 amount,\n uint256 amount0,\n uint256 amount1\n );\n\n /// @notice Emitted by the pool for any swaps between token0 and token1\n /// @param sender The address that initiated the swap call, and that received the callback\n /// @param recipient The address that received the output of the swap\n /// @param amount0 The delta of the token0 balance of the pool\n /// @param amount1 The delta of the token1 balance of the pool\n /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\n /// @param liquidity The liquidity of the pool after the swap\n /// @param tick The log base 1.0001 of price of the pool after the swap\n event Swap(\n address indexed sender,\n address indexed recipient,\n int256 amount0,\n int256 amount1,\n uint160 sqrtPriceX96,\n uint128 liquidity,\n int24 tick\n );\n\n /// @notice Emitted by the pool for any flashes of token0/token1\n /// @param sender The address that initiated the swap call, and that received the callback\n /// @param recipient The address that received the tokens from flash\n /// @param amount0 The amount of token0 that was flashed\n /// @param amount1 The amount of token1 that was flashed\n /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\n /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\n event Flash(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1,\n uint256 paid0,\n uint256 paid1\n );\n\n /// @notice Emitted by the pool for increases to the number of observations that can be stored\n /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\n /// just before a mint/swap/burn.\n /// @param observationCardinalityNextOld The previous value of the next observation cardinality\n /// @param observationCardinalityNextNew The updated value of the next observation cardinality\n event IncreaseObservationCardinalityNext(\n uint16 observationCardinalityNextOld,\n uint16 observationCardinalityNextNew\n );\n\n /// @notice Emitted when the protocol fee is changed by the pool\n /// @param feeProtocol0Old The previous value of the token0 protocol fee\n /// @param feeProtocol1Old The previous value of the token1 protocol fee\n /// @param feeProtocol0New The updated value of the token0 protocol fee\n /// @param feeProtocol1New The updated value of the token1 protocol fee\n event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);\n\n /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\n /// @param sender The address that collects the protocol fees\n /// @param recipient The address that receives the collected protocol fees\n /// @param amount0 The amount of token0 protocol fees that is withdrawn\n /// @param amount0 The amount of token1 protocol fees that is withdrawn\n event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);\n}\n" + }, + "@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Pool state that never changes\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\ninterface IUniswapV3PoolImmutables {\n /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\n /// @return The contract address\n function factory() external view returns (address);\n\n /// @notice The first of the two tokens of the pool, sorted by address\n /// @return The token contract address\n function token0() external view returns (address);\n\n /// @notice The second of the two tokens of the pool, sorted by address\n /// @return The token contract address\n function token1() external view returns (address);\n\n /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\n /// @return The fee\n function fee() external view returns (uint24);\n\n /// @notice The pool tick spacing\n /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\n /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\n /// This value is an int24 to avoid casting even though it is always positive.\n /// @return The tick spacing\n function tickSpacing() external view returns (int24);\n\n /// @notice The maximum amount of position liquidity that can use any tick in the range\n /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\n /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\n /// @return The max amount of liquidity per tick\n function maxLiquidityPerTick() external view returns (uint128);\n}\n" + }, + "@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Permissioned pool actions\n/// @notice Contains pool methods that may only be called by the factory owner\ninterface IUniswapV3PoolOwnerActions {\n /// @notice Set the denominator of the protocol's % share of the fees\n /// @param feeProtocol0 new protocol fee for token0 of the pool\n /// @param feeProtocol1 new protocol fee for token1 of the pool\n function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\n\n /// @notice Collect the protocol fee accrued to the pool\n /// @param recipient The address to which collected protocol fees should be sent\n /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\n /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\n /// @return amount0 The protocol fee collected in token0\n /// @return amount1 The protocol fee collected in token1\n function collectProtocol(\n address recipient,\n uint128 amount0Requested,\n uint128 amount1Requested\n ) external returns (uint128 amount0, uint128 amount1);\n}\n" + }, + "@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Pool state that can change\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\n/// per transaction\ninterface IUniswapV3PoolState {\n /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\n /// when accessed externally.\n /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\n /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\n /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\n /// boundary.\n /// observationIndex The index of the last oracle observation that was written,\n /// observationCardinality The current maximum number of observations stored in the pool,\n /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\n /// feeProtocol The protocol fee for both tokens of the pool.\n /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\n /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\n /// unlocked Whether the pool is currently locked to reentrancy\n function slot0()\n external\n view\n returns (\n uint160 sqrtPriceX96,\n int24 tick,\n uint16 observationIndex,\n uint16 observationCardinality,\n uint16 observationCardinalityNext,\n uint8 feeProtocol,\n bool unlocked\n );\n\n /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\n /// @dev This value can overflow the uint256\n function feeGrowthGlobal0X128() external view returns (uint256);\n\n /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\n /// @dev This value can overflow the uint256\n function feeGrowthGlobal1X128() external view returns (uint256);\n\n /// @notice The amounts of token0 and token1 that are owed to the protocol\n /// @dev Protocol fees will never exceed uint128 max in either token\n function protocolFees() external view returns (uint128 token0, uint128 token1);\n\n /// @notice The currently in range liquidity available to the pool\n /// @dev This value has no relationship to the total liquidity across all ticks\n function liquidity() external view returns (uint128);\n\n /// @notice Look up information about a specific tick in the pool\n /// @param tick The tick to look up\n /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\n /// tick upper,\n /// liquidityNet how much liquidity changes when the pool price crosses the tick,\n /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\n /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\n /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\n /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\n /// secondsOutside the seconds spent on the other side of the tick from the current tick,\n /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\n /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\n /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\n /// a specific position.\n function ticks(int24 tick)\n external\n view\n returns (\n uint128 liquidityGross,\n int128 liquidityNet,\n uint256 feeGrowthOutside0X128,\n uint256 feeGrowthOutside1X128,\n int56 tickCumulativeOutside,\n uint160 secondsPerLiquidityOutsideX128,\n uint32 secondsOutside,\n bool initialized\n );\n\n /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\n function tickBitmap(int16 wordPosition) external view returns (uint256);\n\n /// @notice Returns the information about a position by the position's key\n /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\n /// @return _liquidity The amount of liquidity in the position,\n /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\n /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\n /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\n /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\n function positions(bytes32 key)\n external\n view\n returns (\n uint128 _liquidity,\n uint256 feeGrowthInside0LastX128,\n uint256 feeGrowthInside1LastX128,\n uint128 tokensOwed0,\n uint128 tokensOwed1\n );\n\n /// @notice Returns data about a specific observation index\n /// @param index The element of the observations array to fetch\n /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\n /// ago, rather than at a specific index in the array.\n /// @return blockTimestamp The timestamp of the observation,\n /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\n /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\n /// Returns initialized whether the observation has been initialized and the values are safe to use\n function observations(uint256 index)\n external\n view\n returns (\n uint32 blockTimestamp,\n int56 tickCumulative,\n uint160 secondsPerLiquidityCumulativeX128,\n bool initialized\n );\n}\n" + }, + "@uniswap/v3-core/contracts/libraries/BitMath.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title BitMath\n/// @dev This library provides functionality for computing bit properties of an unsigned integer\nlibrary BitMath {\n /// @notice Returns the index of the most significant bit of the number,\n /// where the least significant bit is at index 0 and the most significant bit is at index 255\n /// @dev The function satisfies the property:\n /// x >= 2**mostSignificantBit(x) and x < 2**(mostSignificantBit(x)+1)\n /// @param x the value for which to compute the most significant bit, must be greater than 0\n /// @return r the index of the most significant bit\n function mostSignificantBit(uint256 x) internal pure returns (uint8 r) {\n require(x > 0);\n\n if (x >= 0x100000000000000000000000000000000) {\n x >>= 128;\n r += 128;\n }\n if (x >= 0x10000000000000000) {\n x >>= 64;\n r += 64;\n }\n if (x >= 0x100000000) {\n x >>= 32;\n r += 32;\n }\n if (x >= 0x10000) {\n x >>= 16;\n r += 16;\n }\n if (x >= 0x100) {\n x >>= 8;\n r += 8;\n }\n if (x >= 0x10) {\n x >>= 4;\n r += 4;\n }\n if (x >= 0x4) {\n x >>= 2;\n r += 2;\n }\n if (x >= 0x2) r += 1;\n }\n\n /// @notice Returns the index of the least significant bit of the number,\n /// where the least significant bit is at index 0 and the most significant bit is at index 255\n /// @dev The function satisfies the property:\n /// (x & 2**leastSignificantBit(x)) != 0 and (x & (2**(leastSignificantBit(x)) - 1)) == 0)\n /// @param x the value for which to compute the least significant bit, must be greater than 0\n /// @return r the index of the least significant bit\n function leastSignificantBit(uint256 x) internal pure returns (uint8 r) {\n require(x > 0);\n\n r = 255;\n if (x & type(uint128).max > 0) {\n r -= 128;\n } else {\n x >>= 128;\n }\n if (x & type(uint64).max > 0) {\n r -= 64;\n } else {\n x >>= 64;\n }\n if (x & type(uint32).max > 0) {\n r -= 32;\n } else {\n x >>= 32;\n }\n if (x & type(uint16).max > 0) {\n r -= 16;\n } else {\n x >>= 16;\n }\n if (x & type(uint8).max > 0) {\n r -= 8;\n } else {\n x >>= 8;\n }\n if (x & 0xf > 0) {\n r -= 4;\n } else {\n x >>= 4;\n }\n if (x & 0x3 > 0) {\n r -= 2;\n } else {\n x >>= 2;\n }\n if (x & 0x1 > 0) r -= 1;\n }\n}\n" + }, + "@uniswap/v3-core/contracts/libraries/SafeCast.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Safe casting methods\n/// @notice Contains methods for safely casting between types\nlibrary SafeCast {\n /// @notice Cast a uint256 to a uint160, revert on overflow\n /// @param y The uint256 to be downcasted\n /// @return z The downcasted integer, now type uint160\n function toUint160(uint256 y) internal pure returns (uint160 z) {\n require((z = uint160(y)) == y);\n }\n\n /// @notice Cast a int256 to a int128, revert on overflow or underflow\n /// @param y The int256 to be downcasted\n /// @return z The downcasted integer, now type int128\n function toInt128(int256 y) internal pure returns (int128 z) {\n require((z = int128(y)) == y);\n }\n\n /// @notice Cast a uint256 to a int256, revert on overflow\n /// @param y The uint256 to be casted\n /// @return z The casted integer, now type int256\n function toInt256(uint256 y) internal pure returns (int256 z) {\n require(y < 2**255);\n z = int256(y);\n }\n}\n" + }, + "contracts/fetchers/CommonFetcher.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\ncontract CommonFetcher {\n uint256 internal constant _DECIMALS = 18;\n bytes4 internal constant _DECIMALS_SELECTOR = bytes4(keccak256(\"decimals()\"));\n\n function _decimals(address _token) internal view virtual returns (uint256 decimals, bool success) {\n bytes memory data;\n\n // solhint-disable-next-line avoid-low-level-calls\n (success, data) = _token.staticcall(abi.encode(_DECIMALS_SELECTOR));\n if (success && data.length != 0) decimals = abi.decode(data, (uint256));\n else success = false;\n }\n\n function _normalizeOneTokenPrice(\n uint256 _amountInDecimals,\n uint256 _baseDecimals,\n uint256 _quoteDecimals,\n uint256 _price\n )\n internal\n pure\n virtual\n returns (uint256 normalizedPrice)\n {\n // normalize price from `amountInDecimals` to `oneToken`\n if (_amountInDecimals == _baseDecimals) {\n normalizedPrice = _price;\n }\n else if (_amountInDecimals < _baseDecimals) {\n normalizedPrice = _price * (10 ** (_baseDecimals - _amountInDecimals));\n } else {\n normalizedPrice = _price / (10 ** (_amountInDecimals - _baseDecimals));\n }\n\n // normalize price to 18 decimals\n if (_quoteDecimals == _DECIMALS) {\n // price OK\n } else if (_quoteDecimals > _DECIMALS) {\n normalizedPrice /= 10 ** (_quoteDecimals - _DECIMALS);\n } else {\n normalizedPrice *= 10 ** (_DECIMALS - _quoteDecimals);\n }\n }\n}\n" + }, + "contracts/fetchers/soveryn/ISovrynSwapNetwork.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\ninterface ISovrynSwapNetwork {\n /**\n * @dev returns the conversion path between two tokens in the network\n * note that this method is quite expensive in terms of gas and should generally be called off-chain\n *\n * @param _sourceToken source token address\n * @param _targetToken target token address\n *\n * @return conversion path between the two tokens\n */\n function conversionPath(address _sourceToken, address _targetToken) external view returns (address[] memory);\n\n /**\n * @dev returns the expected target amount of converting a given amount on a given path\n * note that there is no support for circular paths\n *\n * @param _path conversion path (see conversion path format above)\n * @param _amount amount of _path[0] tokens received from the sender\n *\n * @return expected target amount\n */\n function rateByPath(address[] calldata _path, uint256 _amount) external view returns (uint256);\n}\n" + }, + "contracts/fetchers/soveryn/SovrynFetcherHelper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.22;\n\nimport {ISovrynSwapNetwork} from \"./ISovrynSwapNetwork.sol\";\nimport {CommonFetcher} from \"../CommonFetcher.sol\";\n\ncontract SovrynFetcherHelper is CommonFetcher {\n struct InputData {\n address base;\n address quote;\n uint8 amountInDecimals;\n }\n\n /// @param price is amount out (normalized to 18 decimals) returned by Sovryn pool for 1 quote token\n struct Price {\n uint256 price;\n bool success;\n }\n\n ISovrynSwapNetwork immutable public sovrynSwapNetwork;\n\n constructor(address _sovrynSwapNetwork) {\n sovrynSwapNetwork = ISovrynSwapNetwork(_sovrynSwapNetwork);\n }\n\n /// @dev this method will return estimations for swap for provided amounts\n function getPrices(InputData[] calldata _data)\n external\n view\n virtual\n returns (Price[] memory prices, uint256 timestamp)\n {\n timestamp = block.timestamp;\n uint256 n = _data.length;\n prices = new Price[](n);\n\n for (uint256 i = 0; i < n; i++) {\n prices[i] = _getPrice(_data[i]);\n }\n }\n\n function _getPrice(InputData memory _data)\n internal\n view\n virtual\n returns (Price memory price)\n {\n (uint256 baseDecimals, bool baseHasDecimals) = _decimals(_data.base);\n if (!baseHasDecimals) return price;\n\n (uint256 quoteDecimals, bool quoteHasDecimals) = _decimals(_data.quote);\n if (!quoteHasDecimals) return price;\n\n (address[] memory path, bool success) = _conversionPath(_data.base, _data.quote);\n if (!success) return price;\n\n (price.price, success) = _rateByPath(path, 10 ** _data.amountInDecimals);\n if (!success) return price;\n\n price.success = true;\n price.price = _normalizeOneTokenPrice(_data.amountInDecimals, baseDecimals, quoteDecimals, price.price);\n }\n\n function _conversionPath(address _base, address _quote)\n internal\n view\n returns (address[] memory conversionPath, bool success)\n {\n try sovrynSwapNetwork.conversionPath(_base, _quote) returns (address[] memory path) {\n return (path, true);\n } catch (bytes memory) {\n // error\n }\n }\n\n function _rateByPath(address[] memory _path, uint256 _amountIn)\n internal\n view\n returns (uint256 amountOut, bool success)\n {\n try sovrynSwapNetwork.rateByPath(_path, _amountIn) returns (uint256 result) {\n return (result, true);\n } catch (bytes memory) {\n // error\n }\n }\n}\n" + }, + "contracts/fetchers/uniswapV3/UniswapV3FetcherHelper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.22;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport {IUniswapV3Factory} from \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\";\nimport {IUniswapV3Pool} from \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\";\nimport {IUniswapV3PoolImmutables} from \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\";\nimport {IQuoterV2} from \"gitmodules/uniswap/v3-periphery/contracts/interfaces/IQuoterV2.sol\";\n\nimport {CommonFetcher} from \"../CommonFetcher.sol\";\n\ncontract UniswapV3FetcherHelper is CommonFetcher {\n struct InputData {\n IUniswapV3Pool pool;\n address base;\n address quote;\n uint8 amountInDecimals;\n }\n\n /// @param price is amount out (normalized to 18 decimals) returned by Uniswap pool for 1 quote token\n struct Price {\n uint256 price;\n bool success;\n }\n\n struct LiquidityData {\n uint160 sqrtPriceX96;\n int24 tick;\n uint256 liquidity;\n }\n\n bytes4 internal constant _SYMBOL_SELECTOR = bytes4(keccak256(\"symbol()\"));\n\n IUniswapV3Factory immutable public uniswapV3Factory;\n IQuoterV2 immutable public uniswapV3Quoter;\n\n constructor(IUniswapV3Factory _factory, IQuoterV2 _quoter) {\n uniswapV3Factory = _factory;\n uniswapV3Quoter = _quoter;\n }\n\n /// @dev this method will return estimations for swap for one base token\n /// it can not be view, but to get estimation you have to call it in a static way\n /// Tokens that do not have `.decimals()` are not supported\n /// @param _data array of PriceData, each PriceData can accept multiple pools per one price, price is fetched from\n /// pool, that has biggest liquidity (quote.balanceOf(pool))\n /// @return prices prices normalized from input amount (10 ** prices[n].amountInDecimals) to one token price\n function getPrices(InputData[] calldata _data)\n external\n virtual\n returns (Price[] memory prices, uint256 timestamp)\n {\n timestamp = block.timestamp;\n uint256 n = _data.length;\n prices = new Price[](n);\n\n for (uint256 i = 0; i < n; i++) {\n prices[i] = _getPrice(_data[i]);\n }\n }\n\n function tokensSymbols(address[] calldata _tokens) external view virtual returns (string[] memory symbols) {\n uint256 n = _tokens.length;\n symbols = new string[](n);\n\n for (uint256 i = 0; i < n; i++) {\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory data) = _tokens[i].staticcall(abi.encode(_SYMBOL_SELECTOR));\n\n symbols[i] = success\n ? data.length == 32 ? string(abi.encodePacked(data)) : abi.decode(data, (string))\n : \"\";\n }\n }\n\n function liquidityData(IUniswapV3Pool[] calldata _pools)\n external\n view\n virtual\n returns (LiquidityData[] memory data)\n {\n uint256 n = _pools.length;\n data = new LiquidityData[](n);\n\n for (uint256 i = 0; i < n; i++) {\n IUniswapV3Pool pool = _pools[i];\n (data[i].sqrtPriceX96, data[i].tick,,,,,) = pool.slot0();\n data[i].liquidity = pool.liquidity();\n }\n }\n\n function _getPrice(InputData memory _data) internal virtual returns (Price memory price) {\n (uint256 baseDecimals, bool baseHasDecimals) = _decimals(_data.base);\n if (!baseHasDecimals) return price;\n\n (uint256 quoteDecimals, bool quoteHasDecimals) = _decimals(_data.quote);\n if (!quoteHasDecimals) return price;\n\n if (address(_data.pool) == address(0)) return price;\n\n (uint24 fee, bool success) = _getPoolFee(_data.pool);\n if (!success) return price;\n\n if (address(_data.pool) != _getPool(_data.base, _data.quote, fee)) return price;\n\n IQuoterV2.QuoteExactInputSingleParams memory params = IQuoterV2.QuoteExactInputSingleParams({\n tokenIn: _data.base,\n tokenOut: _data.quote,\n amountIn: 10 ** _data.amountInDecimals,\n fee: fee,\n sqrtPriceLimitX96: 0\n });\n\n try uniswapV3Quoter.quoteExactInputSingle(params)\n returns (uint256 tokenPrice, uint160, uint32, uint256)\n {\n price.price = _normalizeOneTokenPrice(_data.amountInDecimals, baseDecimals, quoteDecimals, tokenPrice);\n price.success = true;\n } catch (bytes memory) {\n // continue;\n }\n }\n\n function _getPool(address _token0, address _token1, uint24 _fee) internal view virtual returns (address pool) {\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory data) = address(uniswapV3Factory).staticcall(\n abi.encodeWithSelector(IUniswapV3Factory.getPool.selector, _token0, _token1, _fee)\n );\n\n if (success) pool = abi.decode(data, (address));\n }\n\n function _getPoolFee(IUniswapV3Pool _pool) internal view virtual returns (uint24 fee, bool success) {\n bytes memory data;\n\n // solhint-disable-next-line avoid-low-level-calls\n (success, data) = address(_pool).staticcall(abi.encodeWithSelector(IUniswapV3PoolImmutables.fee.selector));\n\n if (data.length == 0) {\n success = false;\n } else if (success) {\n fee = abi.decode(data, (uint24));\n }\n }\n}\n" + }, + "contracts/interfaces/AggregatorV3Interface.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface AggregatorV3Interface {\n function decimals() external view returns (uint8);\n\n function description() external view returns (string memory);\n\n function version() external view returns (uint256);\n\n // getRoundData and latestRoundData should both raise \"No data present\"\n // if they do not have data to report, instead of returning unset values\n // which could be misinterpreted as actual reported values.\n function latestRoundData()\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n}\n" + }, + "contracts/interfaces/IBaseChainV1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IBaseChainV1 {\n /// @dev number of blocks (consensus rounds) saved in this contract\n function blocksCount() external returns (uint32);\n\n /// @dev number of all blocks that were generated before switching to this contract\n /// please note, that there might be a gap of one block when we switching from old to new contract\n /// see constructor for details\n function blocksCountOffset() external returns (uint32);\n\n function getLatestBlockId() external view returns (uint32);\n\n function getBlockTimestamp(uint32 _blockId) external view returns (uint32);\n\n function getStatus() external view returns (\n uint256 blockNumber,\n uint16 timePadding,\n uint32 lastDataTimestamp,\n uint32 lastId,\n uint32 nextBlockId\n );\n}\n" + }, + "contracts/interfaces/IUmbrellaFeeds.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IUmbrellaFeeds {\n struct PriceData {\n /// @dev this is placeholder, that can be used for some additional data\n /// atm of creating this smart contract, it is only used as marker for removed data (when == type(uint8).max)\n uint8 data;\n /// @dev heartbeat: how often price data will be refreshed in case price stay flat\n uint24 heartbeat;\n /// @dev timestamp: price time, at this time validators run consensus\n uint32 timestamp;\n /// @dev price\n uint128 price;\n }\n\n struct Signature {\n uint8 v;\n bytes32 r;\n bytes32 s;\n }\n\n /// @dev method for submitting consensus data\n /// @param _priceKeys array of keys for `_priceDatas`\n /// @param _priceDatas PriceData signed by validators\n /// @param _signatures validators signatures\n function update(\n bytes32[] calldata _priceKeys,\n PriceData[] calldata _priceDatas,\n Signature[] calldata _signatures\n ) external;\n\n /// @dev it will return array of price datas for provided `_keys`\n /// In case ony of feed does not exist, fallback call will be executed for that feed.\n /// @notice If data for any key not exists, function will revert. Use `getManyPriceDataRaw` method if you don't\n /// want revert.\n /// @param _keys array of feed keys\n /// @return data PriceData array\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data);\n\n /// @dev same as getManyPriceData() but does not revert on empty data.\n /// @notice This method does no revert if some data does not exists.\n /// Check `data.timestamp` to see if price exist, if it is 0, then it does not exist.\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data);\n\n /// @dev this is main endpoint for reading feeds.\n /// In case timestamp is empty (that means there is no data), contract will revert.\n /// If you do not need whole data from `PriceData` struct, you can save some gas by using other view methods that\n /// returns just what you need.\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return data full PriceData struct\n function getPriceData(bytes32 _key) external view returns (PriceData memory data);\n\n /// @notice reader for mapping\n /// @param _key hash of feed name\n /// @return data full PriceData struct\n function prices(bytes32 _key) external view returns (PriceData memory data);\n\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return price\n function getPrice(bytes32 _key) external view returns (uint128 price);\n\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return price\n /// @return timestamp\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp);\n\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return price\n /// @return timestamp\n /// @return heartbeat\n function getPriceTimestampHeartbeat(bytes32 _key)\n external\n view\n returns (uint128 price, uint32 timestamp, uint24 heartbeat);\n\n /// @dev This method should be used only for Layer2 as it is more gas consuming than others views.\n /// @notice It does not revert on empty data.\n /// @param _name string feed name\n /// @return data PriceData\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data);\n\n /// @dev decimals for prices stored in this contract\n function DECIMALS() external view returns (uint8); // solhint-disable-line func-name-mixedcase\n}\n" + }, + "gitmodules/uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Immutable state\n/// @notice Functions that return immutable state of the router\ninterface IPeripheryImmutableState {\n /// @return Returns the address of the Uniswap V3 factory\n function factory() external view returns (address);\n\n /// @return Returns the address of WETH9\n function WETH9() external view returns (address);\n}\n" + }, + "gitmodules/uniswap/v3-periphery/contracts/interfaces/IQuoterV2.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.7.5;\npragma abicoder v2;\n\n/// @title QuoterV2 Interface\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps.\n/// @notice For each pool also tells you the number of initialized ticks crossed and the sqrt price of the pool after the swap.\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\ninterface IQuoterV2 {\n /// @notice Returns the amount out received for a given exact input swap without executing the swap\n /// @param path The path of the swap, i.e. each token pair and the pool fee\n /// @param amountIn The amount of the first token to swap\n /// @return amountOut The amount of the last token that would be received\n /// @return sqrtPriceX96AfterList List of the sqrt price after the swap for each pool in the path\n /// @return initializedTicksCrossedList List of the initialized ticks that the swap crossed for each pool in the path\n /// @return gasEstimate The estimate of the gas that the swap consumes\n function quoteExactInput(bytes memory path, uint256 amountIn)\n external\n returns (\n uint256 amountOut,\n uint160[] memory sqrtPriceX96AfterList,\n uint32[] memory initializedTicksCrossedList,\n uint256 gasEstimate\n );\n\n struct QuoteExactInputSingleParams {\n address tokenIn;\n address tokenOut;\n uint256 amountIn;\n uint24 fee;\n uint160 sqrtPriceLimitX96;\n }\n\n /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\n /// @param params The params for the quote, encoded as `QuoteExactInputSingleParams`\n /// tokenIn The token being swapped in\n /// tokenOut The token being swapped out\n /// fee The fee of the token pool to consider for the pair\n /// amountIn The desired input amount\n /// sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\n /// @return amountOut The amount of `tokenOut` that would be received\n /// @return sqrtPriceX96After The sqrt price of the pool after the swap\n /// @return initializedTicksCrossed The number of initialized ticks that the swap crossed\n /// @return gasEstimate The estimate of the gas that the swap consumes\n function quoteExactInputSingle(QuoteExactInputSingleParams memory params)\n external\n returns (\n uint256 amountOut,\n uint160 sqrtPriceX96After,\n uint32 initializedTicksCrossed,\n uint256 gasEstimate\n );\n\n /// @notice Returns the amount in required for a given exact output swap without executing the swap\n /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\n /// @param amountOut The amount of the last token to receive\n /// @return amountIn The amount of first token required to be paid\n /// @return sqrtPriceX96AfterList List of the sqrt price after the swap for each pool in the path\n /// @return initializedTicksCrossedList List of the initialized ticks that the swap crossed for each pool in the path\n /// @return gasEstimate The estimate of the gas that the swap consumes\n function quoteExactOutput(bytes memory path, uint256 amountOut)\n external\n returns (\n uint256 amountIn,\n uint160[] memory sqrtPriceX96AfterList,\n uint32[] memory initializedTicksCrossedList,\n uint256 gasEstimate\n );\n\n struct QuoteExactOutputSingleParams {\n address tokenIn;\n address tokenOut;\n uint256 amount;\n uint24 fee;\n uint160 sqrtPriceLimitX96;\n }\n\n /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\n /// @param params The params for the quote, encoded as `QuoteExactOutputSingleParams`\n /// tokenIn The token being swapped in\n /// tokenOut The token being swapped out\n /// fee The fee of the token pool to consider for the pair\n /// amountOut The desired output amount\n /// sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\n /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\n /// @return sqrtPriceX96After The sqrt price of the pool after the swap\n /// @return initializedTicksCrossed The number of initialized ticks that the swap crossed\n /// @return gasEstimate The estimate of the gas that the swap consumes\n function quoteExactOutputSingle(QuoteExactOutputSingleParams memory params)\n external\n returns (\n uint256 amountIn,\n uint160 sqrtPriceX96After,\n uint32 initializedTicksCrossed,\n uint256 gasEstimate\n );\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": false, + "runs": 0 + }, + "evmVersion": "paris", + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/eth_production/solcInputs/dc68422c0ad35a4fe46d461b096b9383.json b/deployments/eth_production/solcInputs/dc68422c0ad35a4fe46d461b096b9383.json new file mode 100644 index 00000000..43238985 --- /dev/null +++ b/deployments/eth_production/solcInputs/dc68422c0ad35a4fe46d461b096b9383.json @@ -0,0 +1,125 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n }\n _balances[to] += amount;\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n _balances[account] += amount;\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n }\n _totalSupply -= amount;\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Trees proofs.\n *\n * The proofs can be generated using the JavaScript library\n * https://github.com/miguelmota/merkletreejs[merkletreejs].\n * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.\n *\n * See `test/utils/cryptography/MerkleProof.test.js` for some examples.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(\n bytes32[] memory proof,\n bytes32 root,\n bytes32 leaf\n ) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n bytes32 proofElement = proof[i];\n if (computedHash <= proofElement) {\n // Hash(current computed hash + current element of the proof)\n computedHash = _efficientHash(computedHash, proofElement);\n } else {\n // Hash(current element of the proof + current computed hash)\n computedHash = _efficientHash(proofElement, computedHash);\n }\n }\n return computedHash;\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "@umb-network/toolbox/dist/contracts/lib/ValueDecoder.sol": { + "content": "//SPDX-License-Identifier: Unlicensed\npragma solidity >=0.6.8;\n\nlibrary ValueDecoder {\n function toUint(bytes memory _bytes) internal pure returns (uint256 value) {\n assembly {\n value := mload(add(_bytes, 32))\n }\n }\n\n function toUint(bytes32 _bytes) internal pure returns (uint256 value) {\n assembly {\n value := _bytes\n }\n }\n\n function toInt(uint224 u) internal pure returns (int256) {\n int224 i;\n uint224 max = type(uint224).max;\n\n if (u <= (max - 1) / 2) { // positive values\n assembly {\n i := add(u, 0)\n }\n\n return i;\n } else { // negative values\n assembly {\n i := sub(sub(u, max), 1)\n }\n }\n\n return i;\n }\n}\n\n" + }, + "contracts/BaseChain.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\";\nimport \"@umb-network/toolbox/dist/contracts/lib/ValueDecoder.sol\";\n\nimport \"./interfaces/IBaseChainV1.sol\";\nimport \"./interfaces/IStakingBank.sol\";\nimport \"./extensions/Registrable.sol\";\nimport \"./Registry.sol\";\n\nabstract contract BaseChain is Registrable, Ownable {\n using ValueDecoder for bytes;\n using ValueDecoder for uint224;\n using MerkleProof for bytes32[];\n\n /// @param root merkle root for consensus\n /// @param dataTimestamp consensus timestamp\n struct Block {\n bytes32 root;\n uint32 dataTimestamp;\n }\n\n /// @param value FCD value\n /// @param dataTimestamp FCD timestamp\n struct FirstClassData {\n uint224 value;\n uint32 dataTimestamp;\n }\n\n /// @param blocksCountOffset number of all blocks that were generated before switching to this contract\n /// @param sequence is a total number of blocks (consensus rounds) including previous contracts\n /// @param lastTimestamp is a timestamp of last submitted block\n /// @param padding number of seconds that need to pass before new submit will be possible\n /// @param deprecated flag that changes to TRUE on `unregister`, when TRUE submissions are not longer available\n struct ConsensusData {\n uint32 blocksCountOffset;\n uint32 sequence;\n uint32 lastTimestamp;\n uint32 padding;\n bool deprecated;\n }\n\n uint256 constant public VERSION = 2;\n\n bool internal immutable _ALLOW_FOR_MIXED_TYPE; // solhint-disable-line var-name-mixedcase\n\n bytes4 constant private _VERSION_SELECTOR = bytes4(keccak256(\"VERSION()\"));\n\n /// @dev minimal number of signatures required for accepting submission (PoA)\n uint16 internal immutable _REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\n\n ConsensusData internal _consensusData;\n\n bytes constant public ETH_PREFIX = \"\\x19Ethereum Signed Message:\\n32\";\n\n /// @dev block id (consensus ID) => root\n /// consensus ID is at the same time consensus timestamp\n mapping(uint256 => bytes32) public roots;\n\n /// @dev FCD key => FCD data\n mapping(bytes32 => FirstClassData) public fcds;\n\n event LogDeprecation(address indexed deprecator);\n event LogPadding(address indexed executor, uint32 timePadding);\n\n error ArraysDataDoNotMatch();\n error AlreadyDeprecated();\n error AlreadyRegistered();\n error BlockSubmittedToFastOrDataToOld();\n error ContractNotReady();\n error FCDOverflow();\n error InvalidContractType();\n error NoChangeToState();\n error OnlyOwnerOrRegistry();\n error UnregisterFirst();\n\n modifier onlyOwnerOrRegistry () {\n if (msg.sender != address(contractRegistry) && msg.sender != owner()) revert OnlyOwnerOrRegistry();\n _;\n }\n\n /// @param _contractRegistry Registry address\n /// @param _padding required \"space\" between blocks in seconds\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n constructor(\n IRegistry _contractRegistry,\n uint32 _padding,\n uint16 _requiredSignatures,\n bool _allowForMixedType\n ) Registrable(_contractRegistry) {\n _ALLOW_FOR_MIXED_TYPE = _allowForMixedType;\n _REQUIRED_SIGNATURES = _requiredSignatures;\n\n _setPadding(_padding);\n\n BaseChain oldChain = BaseChain(_contractRegistry.getAddress(\"Chain\"));\n\n if (address(oldChain) == address(0)) {\n // if this is first contract in sidechain, then we need to initialise lastTimestamp so submission\n // can be possible\n _consensusData.lastTimestamp = uint32(block.timestamp) - _padding - 1;\n }\n }\n\n /// @dev setter for `padding`\n function setPadding(uint16 _padding) external {\n _setPadding(_padding);\n }\n\n /// @notice if this method needs to be called manually (not from Registry)\n /// it is important to do it as part of tx batch\n /// eg using multisig, we should prepare set of transactions and confirm them all at once\n /// @inheritdoc Registrable\n function register() external override onlyOwnerOrRegistry {\n address oldChain = contractRegistry.getAddress(\"Chain\");\n\n // registration must be done before address in registry is replaced\n if (oldChain == address(this)) revert AlreadyRegistered();\n\n if (oldChain == address(0x0)) {\n return;\n }\n\n _cloneLastDataFromPrevChain(oldChain);\n }\n\n /// @inheritdoc Registrable\n function unregister() external override onlyOwnerOrRegistry {\n // in case we deprecated contract manually, we simply return\n if (_consensusData.deprecated) return;\n\n address newChain = contractRegistry.getAddress(\"Chain\");\n // unregistering must be done after address in registry is replaced\n if (newChain == address(this)) revert UnregisterFirst();\n\n // TODO:\n // I think we need to remove restriction for type (at least once)\n // when we will switch to multichain architecture\n\n if (!_ALLOW_FOR_MIXED_TYPE) {\n // can not be replaced with chain of different type\n if (BaseChain(newChain).isForeign() != this.isForeign()) revert InvalidContractType();\n }\n\n _consensusData.deprecated = true;\n emit LogDeprecation(msg.sender);\n }\n\n /// @notice it allows to deprecate contract manually\n /// Only new Registry calls `unregister()` where we set deprecated to true\n /// In old Registries we don't have this feature, so in order to safely redeploy new Chain\n /// we will have to first deprecate current contract manually, then register new contract\n function deprecate() external onlyOwnerOrRegistry {\n if (_consensusData.deprecated) revert AlreadyDeprecated();\n\n _consensusData.deprecated = true;\n emit LogDeprecation(msg.sender);\n }\n\n /// @dev getter for `_consensusData`\n function getConsensusData() external view returns (ConsensusData memory) {\n return _consensusData;\n }\n\n /// @dev number of blocks (consensus rounds) saved in this contract\n function blocksCount() external view returns (uint256) {\n return _consensusData.sequence - _consensusData.blocksCountOffset;\n }\n\n function blocksCountOffset() external view returns (uint32) {\n return _consensusData.blocksCountOffset;\n }\n\n function lastBlockId() external view returns (uint256) {\n return _consensusData.lastTimestamp;\n }\n\n /// @return TRUE if contract is ForeignChain, FALSE otherwise\n function isForeign() external pure virtual returns (bool);\n\n /// @inheritdoc Registrable\n function getName() external pure override returns (bytes32) {\n return \"Chain\";\n }\n\n /// @param _affidavit root and FCDs hashed together\n /// @param _v part of signature\n /// @param _r part of signature\n /// @param _s part of signature\n /// @return signer address\n function recoverSigner(bytes32 _affidavit, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _affidavit));\n return ecrecover(hash, _v, _r, _s);\n }\n\n /// @param _blockId ID of submitted block\n /// @return block data (root + timestamp)\n function blocks(uint256 _blockId) external view returns (Block memory) {\n return Block(roots[_blockId], uint32(_blockId));\n }\n\n /// @return current block ID\n /// please note, that current ID is not the same as last ID, current means that once padding pass,\n /// ID will switch to next one and it will be pointing to empty submit until submit for that ID is done\n function getBlockId() external view returns (uint32) {\n if (_consensusData.lastTimestamp == 0) return 0;\n\n return getBlockIdAtTimestamp(block.timestamp);\n }\n\n function requiredSignatures() external view returns (uint16) {\n return _REQUIRED_SIGNATURES;\n }\n\n /// @dev calculates block ID for provided timestamp\n /// this function does not works for past timestamps\n /// @param _timestamp current or future timestamp\n /// @return block ID for provided timestamp\n function getBlockIdAtTimestamp(uint256 _timestamp) virtual public view returns (uint32) {\n ConsensusData memory data = _consensusData;\n\n unchecked {\n // we can't overflow because we adding two `uint32`\n if (data.lastTimestamp + data.padding < _timestamp) {\n return uint32(_timestamp);\n }\n }\n\n return data.lastTimestamp;\n }\n\n /// @return last submitted block ID, please note, that on deployment, when there is no submission for this contract\n /// block for last ID will be available in previous contract\n function getLatestBlockId() virtual public view returns (uint32) {\n return _consensusData.lastTimestamp;\n }\n\n /// @dev verifies if the leaf is valid leaf for merkle tree\n /// @param _proof merkle proof for merkle tree\n /// @param _root merkle root\n /// @param _leaf leaf hash\n /// @return TRUE if `_leaf` is valid, FALSE otherwise\n function verifyProof(bytes32[] memory _proof, bytes32 _root, bytes32 _leaf) public pure returns (bool) {\n if (_root == bytes32(0)) {\n return false;\n }\n\n return _proof.verify(_root, _leaf);\n }\n\n /// @dev creates leaf hash, that has is used in merkle tree\n /// @param _key key under which we store the value\n /// @param _value value itself as bytes\n /// @return leaf hash\n function hashLeaf(bytes memory _key, bytes memory _value) public pure returns (bytes32) {\n return keccak256(abi.encodePacked(_key, _value));\n }\n\n /// @dev verifies, if provided key-value pair was part of consensus\n /// @param _blockId consensus ID for which we doing a check\n /// @param _proof merkle proof for pair\n /// @param _key pair key\n /// @param _value pair value\n /// @return TRUE if key-value par was part of consensus, FALSE otherwise\n function verifyProofForBlock(\n uint256 _blockId,\n bytes32[] memory _proof,\n bytes memory _key,\n bytes memory _value\n )\n public\n view\n returns (bool)\n {\n return _proof.verify(roots[_blockId], keccak256(abi.encodePacked(_key, _value)));\n }\n\n /// @dev this is helper method, that extracts one merkle proof from many hashed provided as bytes\n /// @param _data many hashes as bytes\n /// @param _offset this is starting point for extraction\n /// @param _items how many hashes to extract\n /// @return merkle proof (array of bytes32 hashes)\n function bytesToBytes32Array(\n bytes memory _data,\n uint256 _offset,\n uint256 _items\n )\n public\n pure\n returns (bytes32[] memory)\n {\n bytes32[] memory dataList = new bytes32[](_items);\n\n // we can unchecked because we working only with `i` and `_offset`\n // in case of wrong `_offset` it will throw\n unchecked {\n for (uint256 i = 0; i < _items; i++) {\n bytes32 temp;\n uint256 idx = (i + 1 + _offset) * 32;\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n temp := mload(add(_data, idx))\n }\n\n dataList[i] = temp;\n }\n }\n\n return (dataList);\n }\n\n /// @dev batch method for data verification\n /// @param _blockIds consensus IDs for which we doing a checks\n /// @param _proofs merkle proofs for all pair, sequence of hashes provided as bytes\n /// @param _proofItemsCounter array of counters, each counter tells how many hashes proof for each leaf has\n /// @param _leaves array of merkle leaves\n /// @return results array of verification results, TRUE if leaf is part of consensus, FALSE otherwise\n function verifyProofs(\n uint32[] memory _blockIds,\n bytes memory _proofs,\n uint256[] memory _proofItemsCounter,\n bytes32[] memory _leaves\n )\n public\n view\n returns (bool[] memory results)\n {\n results = new bool[](_leaves.length);\n uint256 offset = 0;\n\n for (uint256 i = 0; i < _leaves.length;) {\n results[i] = bytesToBytes32Array(_proofs, offset, _proofItemsCounter[i]).verify(\n roots[_blockIds[i]], _leaves[i]\n );\n\n unchecked {\n // we can uncheck because it will not overflow in a lifetime, and if someone provide invalid counter\n // we verification will not be valid (or we throw because of invalid memory access)\n offset += _proofItemsCounter[i];\n // we can uncheck because `i` will not overflow in a lifetime\n i++;\n }\n }\n }\n\n /// @param _blockId consensus ID\n /// @return root for provided consensus ID\n function getBlockRoot(uint32 _blockId) external view returns (bytes32) {\n return roots[_blockId];\n }\n\n /// @param _blockId consensus ID\n /// @return timestamp for provided consensus ID\n function getBlockTimestamp(uint32 _blockId) external view returns (uint32) {\n return roots[_blockId] == bytes32(0) ? 0 : _blockId;\n }\n\n /// @dev batch getter for FCDs\n /// @param _keys FCDs keys to fetch\n /// @return values array of FCDs values\n /// @return timestamps array of FCDs timestamps\n function getCurrentValues(bytes32[] calldata _keys)\n external\n view\n returns (uint256[] memory values, uint32[] memory timestamps)\n {\n timestamps = new uint32[](_keys.length);\n values = new uint256[](_keys.length);\n\n for (uint i=0; i<_keys.length;) {\n FirstClassData storage numericFCD = fcds[_keys[i]];\n values[i] = uint256(numericFCD.value);\n timestamps[i] = numericFCD.dataTimestamp;\n\n unchecked {\n // we can uncheck because `i` will not overflow in a lifetime\n i++;\n }\n }\n }\n\n /// @dev getter for single FCD value\n /// @param _key FCD key\n /// @return value FCD value\n /// @return timestamp FCD timestamp\n function getCurrentValue(bytes32 _key) external view returns (uint256 value, uint256 timestamp) {\n FirstClassData storage numericFCD = fcds[_key];\n return (uint256(numericFCD.value), numericFCD.dataTimestamp);\n }\n\n /// @dev getter for single FCD value in case its type is `int`\n /// @param _key FCD key\n /// @return value FCD value\n /// @return timestamp FCD timestamp\n function getCurrentIntValue(bytes32 _key) external view returns (int256 value, uint256 timestamp) {\n FirstClassData storage numericFCD = fcds[_key];\n return (numericFCD.value.toInt(), numericFCD.dataTimestamp);\n }\n\n function _setPadding(uint32 _padding) internal onlyOwner {\n if (_consensusData.padding == _padding) revert NoChangeToState();\n\n _consensusData.padding = _padding;\n emit LogPadding(msg.sender, _padding);\n }\n\n /// @dev we cloning last block time, because we will need reference point for next submissions\n function _cloneLastDataFromPrevChain(address _prevChain) internal {\n (bool success, bytes memory v) = _prevChain.staticcall(abi.encode(_VERSION_SELECTOR));\n uint256 prevVersion = success ? abi.decode(v, (uint256)) : 1;\n\n if (prevVersion == 1) {\n uint32 latestId = IBaseChainV1(address(_prevChain)).getLatestBlockId();\n _consensusData.lastTimestamp = IBaseChainV1(address(_prevChain)).getBlockTimestamp(latestId);\n\n // +1 because getLatestBlockId subtracts 1\n // +1 because it might be situation when tx is already in progress in old contract\n // and old contract do not have deprecated flag\n _consensusData.sequence = latestId + 2;\n _consensusData.blocksCountOffset = latestId + 2;\n } else { // VERSION 2\n // with new Registry, we have register/unregister methods\n // Chain will be deprecated, so there is no need to do \"+1\" as in old version\n // TODO what with current Registries??\n // we need a way to make it deprecated!\n ConsensusData memory data = BaseChain(_prevChain).getConsensusData();\n\n _consensusData.sequence = data.sequence;\n _consensusData.blocksCountOffset = data.sequence;\n _consensusData.lastTimestamp = data.lastTimestamp;\n }\n }\n}\n" + }, + "contracts/Chain.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./BaseChain.sol\";\n\ncontract Chain is BaseChain {\n IStakingBank public immutable stakingBank;\n\n event LogMint(address indexed minter, uint256 blockId, uint256 staked, uint256 power);\n event LogVoter(uint256 indexed blockId, address indexed voter, uint256 vote);\n\n error NotEnoughSignatures();\n error SignaturesOutOfOrder();\n\n /// @param _contractRegistry Registry address\n /// @param _padding required \"space\" between blocks in seconds\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n /// @param _allowForMixedType we have two \"types\" of Chain: HomeChain and ForeignChain, when we redeploying\n /// we don't want to mix up them, so we checking, if new Chain has the same type as current one.\n /// However, when we will be switching from one homechain to another one, we have to allow for this mixing up.\n /// This flag will tell contract, if this is the case.\n constructor(\n IRegistry _contractRegistry,\n uint32 _padding,\n uint16 _requiredSignatures,\n bool _allowForMixedType\n ) BaseChain(_contractRegistry, _padding, _requiredSignatures, _allowForMixedType) {\n stakingBank = IStakingBank(_contractRegistry.requireAndGetAddress(\"StakingBank\"));\n }\n\n /// @dev method for submitting consensus data\n /// @param _dataTimestamp consensus timestamp, this is time for all data in merkle tree including FCDs\n /// @param _root merkle root\n /// @param _keys FCDs keys\n /// @param _values FCDs values\n /// @param _v array of `v` part of validators signatures\n /// @param _r array of `r` part of validators signatures\n /// @param _s array of `s` part of validators signatures\n // solhint-disable-next-line function-max-lines, code-complexity\n function submit(\n uint32 _dataTimestamp,\n bytes32 _root,\n bytes32[] memory _keys,\n uint256[] memory _values,\n uint8[] memory _v,\n bytes32[] memory _r,\n bytes32[] memory _s\n ) external {\n // below two checks are only for pretty errors, so we can safe gas and allow for raw revert\n // if (_keys.length != _values.length) revert ArraysDataDoNotMatch();\n // if (_v.length != _r.length || _r.length != _s.length) revert ArraysDataDoNotMatch();\n\n _verifySubmitTimestampAndIncSequence(_dataTimestamp);\n\n // we can't expect minter will have exactly the same timestamp\n // but for sure we can demand not to be off by a lot, that's why +3sec\n // temporary remove this condition, because recently on ropsten we see cases when minter/node\n // can be even 100sec behind\n // require(_dataTimestamp <= block.timestamp + 3,\n // string(abi.encodePacked(\"oh, so you can predict the future:\", _dataTimestamp - block.timestamp + 48)));\n\n bytes memory testimony = abi.encodePacked(_dataTimestamp, _root);\n\n for (uint256 i = 0; i < _keys.length;) {\n if (uint224(_values[i]) != _values[i]) revert FCDOverflow();\n\n fcds[_keys[i]] = FirstClassData(uint224(_values[i]), _dataTimestamp);\n testimony = abi.encodePacked(testimony, _keys[i], _values[i]);\n\n unchecked {\n // we can't pass enough data to overflow\n i++;\n }\n }\n\n uint256 signatures = 0;\n uint256 power = 0;\n //uint256 staked = stakingBank.totalSupply();\n bytes32 affidavit = keccak256(testimony);\n\n address prevSigner = address(0x0);\n\n for (uint256 i; i < _v.length;) {\n address signer = recoverSigner(affidavit, _v[i], _r[i], _s[i]);\n uint256 balance = stakingBank.balanceOf(signer);\n\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\n\n prevSigner = signer;\n\n if (balance == 0) {\n unchecked { i++; }\n continue;\n }\n\n signatures++;\n emit LogVoter(uint256(_dataTimestamp), signer, balance);\n\n unchecked {\n // we can't overflow because that means token overflowed\n // and even if we do, we will get lower power\n power += balance;\n i++;\n }\n }\n\n if (signatures < _REQUIRED_SIGNATURES) revert NotEnoughSignatures();\n\n emit LogMint(msg.sender, _dataTimestamp, stakingBank.totalSupply(), power);\n\n // TODO remember to protect against flash loans when DPoS will be in place\n // we turn on power once we have DPoS in action, we have PoA now\n // require(power * 100 / staked >= 66, \"not enough power was gathered\");\n\n roots[_dataTimestamp] = _root;\n _consensusData.lastTimestamp = _dataTimestamp;\n }\n\n /// @inheritdoc BaseChain\n function isForeign() external pure virtual override returns (bool) {\n return false;\n }\n\n /// @dev helper method that returns all important data about current state of contract\n /// @return blockNumber `block.number`\n /// @return timePadding `this.padding`\n /// @return lastDataTimestamp timestamp for last submitted consensus\n /// @return lastId ID of last submitted consensus\n /// @return nextLeader leader for `block.timestamp + 1`\n /// @return nextBlockId block ID for `block.timestamp + padding`\n /// @return validators array of all validators addresses\n /// @return powers array of all validators powers\n /// @return locations array of all validators locations\n /// @return staked total UMB staked by validators\n /// @return minSignatures `this.requiredSignatures`\n function getStatus() external view virtual returns(\n uint256 blockNumber,\n uint32 timePadding,\n uint32 lastDataTimestamp,\n uint32 lastId,\n address nextLeader,\n uint32 nextBlockId,\n address[] memory validators,\n uint256[] memory powers,\n string[] memory locations,\n uint256 staked,\n uint16 minSignatures\n ) {\n ConsensusData memory data = _consensusData;\n\n blockNumber = block.number;\n timePadding = data.padding;\n lastId = data.lastTimestamp;\n lastDataTimestamp = lastId;\n minSignatures = _REQUIRED_SIGNATURES;\n\n staked = stakingBank.totalSupply();\n uint256 numberOfValidators = stakingBank.getNumberOfValidators();\n powers = new uint256[](numberOfValidators);\n validators = new address[](numberOfValidators);\n locations = new string[](numberOfValidators);\n\n for (uint256 i = 0; i < numberOfValidators;) {\n validators[i] = stakingBank.addresses(i);\n (, locations[i]) = stakingBank.validators(validators[i]);\n powers[i] = stakingBank.balanceOf(validators[i]);\n\n unchecked {\n // we will run out of gas before overflow happen\n i++;\n }\n }\n\n unchecked {\n // we will not overflow with timestamp in a lifetime\n nextBlockId = lastId + data.padding + 1;\n\n nextLeader = numberOfValidators > 0\n // we will not overflow with timestamp in a lifetime\n ? validators[getLeaderIndex(numberOfValidators, block.timestamp + 1)]\n : address(0);\n }\n }\n\n /// @return address of leader for next second\n function getNextLeaderAddress() external view returns (address) {\n return getLeaderAddressAtTime(block.timestamp + 1);\n }\n\n /// @return address of current leader\n function getLeaderAddress() external view returns (address) {\n return getLeaderAddressAtTime(block.timestamp);\n }\n\n /// @param _numberOfValidators total number of validators\n /// @param _timestamp timestamp for which you want to calculate index\n /// @return leader index, use it for StakingBank.addresses[index] to fetch leader address\n function getLeaderIndex(uint256 _numberOfValidators, uint256 _timestamp) public view virtual returns (uint256) {\n ConsensusData memory data = _consensusData;\n\n unchecked {\n // we will not overflow on `timestamp` and `padding` in a life time\n // timePadding + 1 => because padding is a space between blocks,\n // so next round starts on first block after padding\n // TODO will it work for off-chain??\n uint256 validatorIndex = data.sequence + (_timestamp - data.lastTimestamp) / (data.padding + 1);\n\n return validatorIndex % _numberOfValidators;\n }\n }\n\n // @todo - properly handled non-enabled validators, newly added validators, and validators with low stake\n /// @param _timestamp timestamp for which you want to calculate leader address\n /// @return leader address for provider timestamp\n function getLeaderAddressAtTime(uint256 _timestamp) public view virtual returns (address) {\n uint256 numberOfValidators = stakingBank.getNumberOfValidators();\n\n if (numberOfValidators == 0) {\n return address(0x0);\n }\n\n uint256 validatorIndex = getLeaderIndex(numberOfValidators, _timestamp);\n\n return stakingBank.addresses(validatorIndex);\n }\n\n /// @dev we had stack too deep in `submit` so this method was created as a solution\n // we increasing `_consensusData.sequence` here so we don't have to read sequence again in other place\n function _verifySubmitTimestampAndIncSequence(uint256 _dataTimestamp) internal {\n ConsensusData memory data = _consensusData;\n\n // `data.lastTimestamp` must be setup either on deployment\n // or via cloning from previous contract\n if (data.lastTimestamp == 0) revert ContractNotReady();\n\n unchecked {\n // we will not overflow with timestamp and padding in a life time\n if (data.lastTimestamp + data.padding >= _dataTimestamp) revert BlockSubmittedToFastOrDataToOld();\n }\n\n unchecked {\n // we will not overflow in a life time\n _consensusData.sequence = uint32(data.sequence + 1);\n }\n }\n}\n" + }, + "contracts/extensions/Registrable.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\n/// @dev Any contract that we want to register in ContractRegistry, must inherit from Registrable\nabstract contract Registrable {\n IRegistry public immutable contractRegistry;\n\n modifier onlyFromContract(address _msgSender, bytes32 _contractName) {\n require(\n contractRegistry.getAddress(_contractName) == _msgSender,\n string(abi.encodePacked(\"caller is not \", _contractName))\n );\n _;\n }\n\n modifier withRegistrySetUp() {\n require(address(contractRegistry) != address(0x0), \"_registry is empty\");\n _;\n }\n\n constructor(IRegistry _contractRegistry) {\n require(address(_contractRegistry) != address(0x0), \"_registry is empty\");\n contractRegistry = _contractRegistry;\n }\n\n /// @dev this method will be called as a first method in registration process when old contract will be replaced\n /// when called, old contract address is still in registry\n function register() virtual external;\n\n /// @dev this method will be called as a last method in registration process when old contract will be replaced\n /// when called, new contract address is already in registry\n function unregister() virtual external;\n\n /// @return contract name as bytes32\n function getName() virtual external pure returns (bytes32);\n\n /// @dev helper method for fetching StakingBank address\n function stakingBankContract() public view returns (IStakingBank) {\n return IStakingBank(contractRegistry.requireAndGetAddress(\"StakingBank\"));\n }\n\n /// @dev helper method for fetching UMB address\n function tokenContract() public view withRegistrySetUp returns (ERC20) {\n return ERC20(contractRegistry.requireAndGetAddress(\"UMB\"));\n }\n}\n" + }, + "contracts/ForeignChain.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./Chain.sol\";\n\n/// @dev contract for foreign chains\ncontract ForeignChain is Chain {\n error NotSupported();\n\n /// @param _contractRegistry Registry address\n /// @param _padding required \"space\" between blocks in seconds\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n constructor(\n IRegistry _contractRegistry,\n uint32 _padding,\n uint16 _requiredSignatures,\n bool _allowForMixedType\n ) Chain(_contractRegistry, _padding, _requiredSignatures, _allowForMixedType) {\n // no additional configuration needed\n }\n\n /// @inheritdoc BaseChain\n function isForeign() external pure override returns (bool) {\n return true;\n }\n\n /// @inheritdoc Chain\n /// @notice this method is made to be compatible with MasterChain, but it does not return full data eg validators\n /// data will be missing.\n /// @return blockNumber `block.number`\n /// @return timePadding `this.padding`\n /// @return lastDataTimestamp timestamp for last submitted consensus\n /// @return lastId ID of last submitted consensus\n /// @return nextLeader will be always address(0)\n /// @return nextBlockId block ID for `block.timestamp + padding`\n /// @return validators array will be always empty\n /// @return powers array will be always empty\n /// @return locations array will be always empty\n /// @return staked total UMB staked by validators\n /// @return minSignatures `this.requiredSignatures`\n function getStatus() external view override returns(\n uint256 blockNumber,\n uint32 timePadding,\n uint32 lastDataTimestamp,\n uint32 lastId,\n address nextLeader,\n uint32 nextBlockId,\n address[] memory validators,\n uint256[] memory powers,\n string[] memory locations,\n uint256 staked,\n uint16 minSignatures\n ) {\n ConsensusData memory data = _consensusData;\n\n blockNumber = block.number;\n timePadding = data.padding;\n lastId = data.lastTimestamp;\n lastDataTimestamp = lastId;\n minSignatures = _REQUIRED_SIGNATURES;\n\n staked = stakingBank.totalSupply();\n uint256 numberOfValidators = 0;\n powers = new uint256[](numberOfValidators);\n validators = new address[](numberOfValidators);\n locations = new string[](numberOfValidators);\n nextLeader = address(0);\n\n unchecked {\n // we will not overflow with timestamp in a lifetime\n nextBlockId = lastId + data.padding + 1;\n }\n }\n\n function getLeaderIndex(uint256, uint256) public pure override returns (uint256) {\n revert NotSupported();\n }\n\n function getLeaderAddressAtTime(uint256) public pure override returns (address) {\n revert NotSupported();\n }\n}\n" + }, + "contracts/interfaces/IBaseChainV1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IBaseChainV1 {\n /// @dev number of blocks (consensus rounds) saved in this contract\n function blocksCount() external returns (uint32);\n\n /// @dev number of all blocks that were generated before switching to this contract\n /// please note, that there might be a gap of one block when we switching from old to new contract\n /// see constructor for details\n function blocksCountOffset() external returns (uint32);\n\n function getLatestBlockId() external view returns (uint32);\n\n function getBlockTimestamp(uint32 _blockId) external view returns (uint32);\n\n function getStatus() external view returns (\n uint256 blockNumber,\n uint16 timePadding,\n uint32 lastDataTimestamp,\n uint32 lastId,\n uint32 nextBlockId\n );\n}\n" + }, + "contracts/interfaces/IRegistry.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\n\ninterface IRegistry {\n event LogRegistered(address indexed destination, bytes32 name);\n\n /// @dev imports new contract addresses and override old addresses, if they exist under provided name\n /// This method can be used for contracts that for some reason do not have `getName` method\n /// @param _names array of contract names that we want to register\n /// @param _destinations array of contract addresses\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external;\n\n /// @dev imports new contracts and override old addresses, if they exist.\n /// Names of contracts are fetched directly from each contract by calling `getName`\n /// @param _destinations array of contract addresses\n function importContracts(address[] calldata _destinations) external;\n\n /// @dev this method ensure, that old and new contract is aware of it state in registry\n /// Note: BSC registry does not have this method. This method was introduced in later stage.\n /// @param _newContract address of contract that will replace old one\n function atomicUpdate(address _newContract) external;\n\n /// @dev similar to `getAddress` but throws when contract name not exists\n /// @param name contract name\n /// @return contract address registered under provided name or throws, if does not exists\n function requireAndGetAddress(bytes32 name) external view returns (address);\n\n /// @param name contract name in a form of bytes32\n /// @return contract address registered under provided name\n function getAddress(bytes32 name) external view returns (address);\n\n /// @param _name contract name\n /// @return contract address assigned to the name or address(0) if not exists\n function getAddressByString(string memory _name) external view returns (address);\n\n /// @dev helper method that converts string to bytes32,\n /// you can use to to generate contract name\n function stringToBytes32(string memory _string) external pure returns (bytes32 result);\n}\n" + }, + "contracts/interfaces/IStakingBank.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IStakingBank is IERC20 {\n /// @param id address of validator wallet\n /// @param location URL of the validator API\n struct Validator {\n address id;\n string location;\n }\n\n event LogValidatorRegistered(address indexed id);\n event LogValidatorUpdated(address indexed id);\n event LogValidatorRemoved(address indexed id);\n event LogMinAmountForStake(uint256 minAmountForStake);\n\n /// @dev setter for `minAmountForStake`\n function setMinAmountForStake(uint256 _minAmountForStake) external;\n\n /// @dev allows to stake `token` by validators\n /// Validator needs to approve StakingBank beforehand\n /// @param _value amount of tokens to stake\n function stake(uint256 _value) external;\n\n /// @dev notification about approval from `_from` address on UMB token\n /// Staking bank will stake max approved amount from `_from` address\n /// @param _from address which approved token spend for IStakingBank\n function receiveApproval(address _from) external returns (bool success);\n\n /// @dev withdraws stake tokens\n /// it throws, when balance will be less than required minimum for stake\n /// to withdraw all use `exit`\n function withdraw(uint256 _value) external returns (bool success);\n\n /// @dev unstake and withdraw all tokens\n function exit() external returns (bool success);\n\n /// @dev creates (register) new validator\n /// @param _id validator address\n /// @param _location location URL of the validator API\n function create(address _id, string calldata _location) external;\n\n /// @dev removes validator\n /// @param _id validator wallet\n function remove(address _id) external;\n\n /// @dev updates validator location\n /// @param _id validator wallet\n /// @param _location new validator URL\n function update(address _id, string calldata _location) external;\n\n /// @return total number of registered validators (with and without balance)\n function getNumberOfValidators() external view returns (uint256);\n\n /// @dev gets validator address for provided index\n /// @param _ix index in array of list of all validators wallets\n function addresses(uint256 _ix) external view returns (address);\n\n /// @param _id address of validator\n /// @return id address of validator\n /// @return location URL of validator\n function validators(address _id) external view returns (address id, string memory location);\n}\n" + }, + "contracts/interfaces/IStakingBankStatic.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./IStakingBank.sol\";\n\n\ninterface IStakingBankStatic is IStakingBank {\n /// @param _validators array of validators addresses to verify\n /// @return TRUE when all validators are valid, FALSE otherwise\n function verifyValidators(address[] calldata _validators) external view returns (bool);\n}\n" + }, + "contracts/interfaces/IUmbrellaFeeds.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IUmbrellaFeeds {\n struct PriceData {\n /// @dev this is placeholder, that can be used for some additional data\n /// atm of creating this smart contract, it is only used as marker for removed data (when == type(uint8).max)\n uint8 data;\n /// @dev heartbeat: how often price data will be refreshed in case price stay flat\n uint24 heartbeat;\n /// @dev timestamp: price time, at this time validators run consensus\n uint32 timestamp;\n /// @dev price\n uint128 price;\n }\n\n struct Signature {\n uint8 v;\n bytes32 r;\n bytes32 s;\n }\n\n /// @dev method for submitting consensus data\n /// @param _priceKeys array of keys for `_priceDatas`\n /// @param _priceDatas PriceData signed by validators\n /// @param _signatures validators signatures\n function update(\n bytes32[] calldata _priceKeys,\n PriceData[] calldata _priceDatas,\n Signature[] calldata _signatures\n ) external;\n\n /// @dev it will return array of price datas for provided `_keys`\n /// In case ony of feed does not exist, fallback call will be executed for that feed.\n /// @notice If data for any key not exists, function will revert. Use `getManyPriceDataRaw` method if you don't\n /// want revert.\n /// @param _keys array of feed keys\n /// @return data PriceData array\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data);\n\n /// @dev same as getManyPriceData() but does not revert on empty data.\n /// @notice This method does no revert if some data does not exists.\n /// Check `data.timestamp` to see if price exist, if it is 0, then it does not exist.\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data);\n\n /// @dev this is main endpoint for reading feeds.\n /// In case timestamp is empty (that means there is no data), contract will revert.\n /// If you do not need whole data from `PriceData` struct, you can save some gas by using other view methods that\n /// returns just what you need.\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return data full PriceData struct\n function getPriceData(bytes32 _key) external view returns (PriceData memory data);\n\n /// @notice reader for mapping\n /// @param _key hash of feed name\n /// @return data full PriceData struct\n function prices(bytes32 _key) external view returns (PriceData memory data);\n\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return price\n function getPrice(bytes32 _key) external view returns (uint128 price);\n\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return price\n /// @return timestamp\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp);\n\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return price\n /// @return timestamp\n /// @return heartbeat\n function getPriceTimestampHeartbeat(bytes32 _key)\n external\n view\n returns (uint128 price, uint32 timestamp, uint24 heartbeat);\n\n /// @dev This method should be used only for Layer2 as it is more gas consuming than others views.\n /// @notice It does not revert on empty data.\n /// @param _name string feed name\n /// @return data PriceData\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data);\n\n /// @dev decimals for prices stored in this contract\n function DECIMALS() external view returns (uint8); // solhint-disable-line func-name-mixedcase\n}\n" + }, + "contracts/interfaces/StakingBankStaticNotSupported.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./IStakingBank.sol\";\n\nabstract contract StakingBankStaticNotSupported is IStakingBank {\n error NotSupported();\n\n function create(address, string calldata) external pure {\n revert NotSupported();\n }\n\n function update(address, string calldata) external pure {\n revert NotSupported();\n }\n\n function remove(address) external pure {\n revert NotSupported();\n }\n\n function transfer(address, uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function transferFrom(address, address, uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function receiveApproval(address) external pure returns (bool) {\n revert NotSupported();\n }\n\n function allowance(address, address) external pure returns (uint256) {\n revert NotSupported();\n }\n\n function approve(address, uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function stake(uint256) external pure {\n revert NotSupported();\n }\n\n function withdraw(uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function exit() external pure returns (bool) {\n revert NotSupported();\n }\n\n function setMinAmountForStake(uint256) external pure {\n revert NotSupported();\n }\n}\n" + }, + "contracts/mock/Distributor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport \"../Registry.sol\";\n\ncontract Distributor is Ownable {\n address[] public recipients;\n uint256 public bottomLimit = 5e17;\n uint256 public topLimit = 1e18;\n\n constructor(address[] memory _recipients) {\n recipients = _recipients;\n }\n\n receive() external payable {\n distribute();\n }\n\n function setLimits(uint256 _bottom, uint256 _top) external onlyOwner {\n bottomLimit = _bottom;\n topLimit = _top;\n }\n\n function withdraw() external {\n uint balance = address(this).balance;\n uint buffer = recipients.length * (topLimit - bottomLimit);\n\n if (balance > buffer) {\n payable(owner()).transfer(balance - buffer);\n }\n }\n\n function addRecipients(address[] calldata _recipients) external onlyOwner {\n for (uint256 i = 0; i < _recipients.length; i++) {\n recipients.push(_recipients[i]);\n }\n }\n\n function removeRecipient(address _recipient) external onlyOwner {\n for (uint256 i = 0; i < recipients.length; i++) {\n if (recipients[i] == _recipient) {\n recipients[i] = recipients[recipients.length - 1];\n recipients.pop();\n return;\n }\n }\n }\n\n function recipientsCount() external view returns (uint256) {\n return recipients.length;\n }\n\n function allRecipients() external view returns (address[] memory) {\n return recipients;\n }\n\n function getName() external pure returns (bytes32) {\n return \"Distributor\";\n }\n\n function distribute() public {\n uint256 limit = bottomLimit;\n uint256 top = topLimit;\n uint256 count = recipients.length;\n uint256 totalBalance = address(this).balance;\n\n for (uint256 i = 0; i < count; i++) {\n uint256 balance = recipients[i].balance;\n\n if (balance > limit) {\n continue;\n }\n\n uint256 amount = top - balance > totalBalance ? totalBalance : top - balance;\n\n if (amount > 0) {\n payable(recipients[i]).transfer(amount);\n totalBalance -= amount;\n }\n }\n }\n}\n" + }, + "contracts/mock/LimitedMintingToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\ncontract LimitedMintingToken is ERC20, Ownable {\n struct MintData {\n uint256 dailyAllowance;\n mapping (address => uint256) lastMintTimestamp;\n mapping (address => uint256) todaysMintedAmount;\n }\n\n MintData public mintData;\n\n constructor(string memory _name, string memory _symbol, uint256 _dailyAllowance) ERC20(_name, _symbol) {\n mintData.dailyAllowance = _dailyAllowance;\n }\n\n function mint(address _holder, uint256 _amount) external {\n MintData storage data = mintData;\n\n (uint256 limit, bool fullLimit) = _currentLimit(data);\n\n require(limit > 0, \"This address already claimed the maximum daily amount\");\n\n uint256 lastTimestamp = data.lastMintTimestamp[msg.sender];\n uint256 mintedAmount = data.todaysMintedAmount[msg.sender];\n\n uint256 amount = _amount > limit ? limit : _amount;\n data.lastMintTimestamp[msg.sender] = fullLimit ? block.timestamp : lastTimestamp;\n data.todaysMintedAmount[msg.sender] = fullLimit ? amount : mintedAmount + amount;\n\n _mint(_holder, amount);\n }\n\n function mintApproveAndStake(IStakingBank _stakingBank, address _holder, uint256 _amount) external {\n _mint(_holder, _amount);\n _approve(_holder, address(_stakingBank), _amount);\n _stakingBank.receiveApproval(_holder);\n }\n\n function getDailyAllowance() external view returns (uint256) {\n return mintData.dailyAllowance;\n }\n\n function getName() external pure returns (bytes32) {\n return \"UMB\";\n }\n\n function setDailyAllowance(uint256 newDailyAllowance) public onlyOwner {\n MintData storage data = mintData;\n data.dailyAllowance = newDailyAllowance;\n }\n\n function _currentLimit(MintData storage data) internal view returns (uint256 limit, bool fullLimit) {\n uint256 lastMint = data.lastMintTimestamp[msg.sender];\n fullLimit = block.timestamp - lastMint >= 24 hours;\n\n uint256 usedLimit = data.todaysMintedAmount[msg.sender];\n\n limit = fullLimit ? data.dailyAllowance : data.dailyAllowance - usedLimit;\n }\n}\n" + }, + "contracts/mock/Token.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\n// please remember this is our dummy token!\n// it will be replaced by proper DPoS solution in future\ncontract Token is ERC20 {\n constructor(\n string memory _name,\n string memory _symbol) ERC20(_name, _symbol) {\n }\n\n function mint(address _holder, uint256 _amount) external {\n _mint(_holder, _amount);\n }\n\n function mintApproveAndStake(IStakingBank _stakingBank, address _holder, uint256 _amount) external {\n _mint(_holder, _amount);\n _approve(_holder, address(_stakingBank), _amount);\n _stakingBank.receiveApproval(_holder);\n }\n\n function getName() external pure returns (bytes32) {\n return \"UMB\";\n }\n}\n" + }, + "contracts/onChainFeeds/UmbrellaFeeds.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/IUmbrellaFeeds.sol\";\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IStakingBankStatic.sol\";\n\n/// @dev Main contract for all on-chain data.\n/// Check `UmbrellaFeedsReader` to see how to integrate.\n///\n/// @notice This contract can be destroyed and replaced with new one (with new address).\n/// For best gas efficiency you should pick one of two ways of integration:\n/// 1. make `UmbrellaFeeds` immutable and use fallback in case of selfdestruct. After new deployment, it is recommended\n/// to update address to avoid fallback and reduce gas cost to minimum. In long run this is most efficient solution,\n/// better than any proxy.\n/// 2. always check newest `UmbrellaFeeds` via `Regostry` and fallback will not be needed.\ncontract UmbrellaFeeds is IUmbrellaFeeds {\n bytes constant public ETH_PREFIX = \"\\x19Ethereum Signed Message:\\n32\";\n string constant public NAME = \"UmbrellaFeeds\";\n\n /// @dev deployment time, used for protect for unintentional destroy\n uint256 public immutable DEPLOYED_AT; // solhint-disable-line var-name-mixedcase\n\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\n /// resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev StakingBank contract where list of validators is stored\n IStakingBankStatic public immutable STAKING_BANK; // solhint-disable-line var-name-mixedcase\n\n /// @dev minimal number of signatures required for accepting price submission (PoA)\n uint16 public immutable REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\n\n /// @dev decimals for prices stored in this contract\n uint8 public immutable DECIMALS; // solhint-disable-line var-name-mixedcase\n\n /// @notice map of all prices stored in this contract, key for map is hash of feed name\n /// eg for \"ETH-USD\" feed, key will be hash(\"ETH-USD\")\n mapping (bytes32 => PriceData) private _prices;\n\n error ArraysDataDoNotMatch();\n error FeedNotExist();\n error NotEnoughSignatures();\n error InvalidSigner();\n error InvalidRequiredSignatures();\n error SignaturesOutOfOrder();\n error ECDSAInvalidSignatureS();\n error ECDSAInvalidSignatureV();\n error OldData();\n error ContractInUse();\n error ContractNotInitialised();\n\n /// @param _contractRegistry Registry address\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n /// @param _decimals decimals for prices stored in this contract\n constructor(\n IRegistry _contractRegistry,\n uint16 _requiredSignatures,\n uint8 _decimals\n ) {\n if (_requiredSignatures == 0) revert InvalidRequiredSignatures();\n\n REGISTRY = _contractRegistry;\n REQUIRED_SIGNATURES = _requiredSignatures;\n STAKING_BANK = IStakingBankStatic(_contractRegistry.requireAndGetAddress(\"StakingBank\"));\n DECIMALS = _decimals;\n DEPLOYED_AT = block.timestamp;\n }\n\n /// @dev destroys old contract\n /// there is sanity check that prevents abuse of destroy method\n /// @param _name string feed key to verify, that contract was initialised\n function destroy(string calldata _name) external {\n if (REGISTRY.getAddressByString(NAME) == address(this)) revert ContractInUse();\n\n if (_prices[keccak256(abi.encodePacked(_name))].timestamp == 0 && DEPLOYED_AT + 3 days > block.timestamp) {\n revert ContractNotInitialised();\n }\n\n selfdestruct(payable(msg.sender));\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function update(\n bytes32[] calldata _priceKeys,\n PriceData[] calldata _priceDatas,\n Signature[] calldata _signatures\n ) external {\n if (_priceKeys.length != _priceDatas.length) revert ArraysDataDoNotMatch();\n\n bytes32 priceDataHash = keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n verifySignatures(priceDataHash, _signatures);\n\n uint256 i;\n\n while (i < _priceDatas.length) {\n bytes32 priceKey = _priceKeys[i];\n\n // we do not allow for older prices\n // at the same time it prevents from reusing signatures\n if (_prices[priceKey].timestamp >= _priceDatas[i].timestamp) revert OldData();\n\n _prices[priceKey] = _priceDatas[i];\n\n // atm there is no need for events, so in order to save gas, we do not emit any\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n if (data[i].timestamp == 0) revert FeedNotExist();\n\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function prices(bytes32 _key) external view returns (PriceData memory data) {\n data = _prices[_key];\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceData(bytes32 _key) external view returns (PriceData memory data) {\n data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPrice(bytes32 _key) external view returns (uint128 price) {\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return data.price;\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp) {\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp);\n }\n\n function getPriceTimestampHeartbeat(bytes32 _key)\n external\n view\n returns (uint128 price, uint32 timestamp, uint24 heartbeat)\n {\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp, data.heartbeat);\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data) {\n bytes32 key = keccak256(abi.encodePacked(_name));\n data = _prices[key];\n }\n\n /// @dev helper method for QA purposes\n /// @return hash of data that are signed by validators (keys and priced data)\n function hashData(bytes32[] calldata _priceKeys, PriceData[] calldata _priceDatas)\n external\n view\n returns (bytes32)\n {\n return keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n }\n\n /// @param _hash hash of signed data\n /// @param _signatures array of validators signatures\n function verifySignatures(bytes32 _hash, Signature[] calldata _signatures) public view {\n address prevSigner = address(0x0);\n\n if (_signatures.length < REQUIRED_SIGNATURES) revert NotEnoughSignatures();\n\n address[] memory validators = new address[](REQUIRED_SIGNATURES);\n\n // to save gas we check only required number of signatures\n // case, where you can have part of signatures invalid but still enough valid in total is not supported\n for (uint256 i; i < REQUIRED_SIGNATURES;) {\n (uint8 v, bytes32 r, bytes32 s) = (_signatures[i].v, _signatures[i].r, _signatures[i].s);\n\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n revert ECDSAInvalidSignatureS();\n }\n\n if (uint8(v) != 27 && uint8(v) != 28) revert ECDSAInvalidSignatureV();\n\n address signer = recoverSigner(_hash, v, r, s);\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\n\n // because we check only required number of signatures, any invalid one will cause revert\n prevSigner = signer;\n validators[i] = signer;\n\n unchecked { i++; }\n }\n\n // bulk verification can optimise gas when we have 5 or more validators\n if (!STAKING_BANK.verifyValidators(validators)) revert InvalidSigner();\n }\n\n function getChainId() public view returns (uint256 id) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n id := chainid()\n }\n }\n\n /// @param _hash hashed of data\n /// @param _v part of signature\n /// @param _r part of signature\n /// @param _s part of signature\n /// @return signer address\n function recoverSigner(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _hash));\n return ecrecover(hash, _v, _r, _s);\n }\n\n /// @dev to follow Registrable interface\n function getName() public pure returns (bytes32) {\n return \"UmbrellaFeeds\";\n }\n}\n" + }, + "contracts/onChainFeeds/UmbrellaFeedsReader.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IUmbrellaFeeds.sol\";\n\n/// @dev This is optional price reader for just one feed.\n/// It comes with chanilink interface that makes migration process easier.\n/// For maximum gas optimisation it is recommended to use UmbrellaFeeds directly - simply follow this contract as\n/// a guide for integration.\n///\n/// This contract has build in fallback feature in case, `UmbrellaFeeds` will be replaced by newer contract.\n/// Fallback is transparent for the user, no additional setup is needed.\n///\n/// How fallback feature works? If data for provided key is empty (when UmbrellaFeeds was destroyed and replaced),\n/// contract will execute following procedure:\n/// 1. if data is empty, contract will check if there is new registered contract with requested data\n/// 2. if data is found in new contract it will be returned\n/// 3. if there is no data or there is no new contract tx will revert.\ncontract UmbrellaFeedsReader {\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\n /// resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev contract where all the feeds are stored\n address public immutable UMBRELLA_FEEDS; // solhint-disable-line var-name-mixedcase\n\n /// @dev key (hash of string key), under which feed is being stored\n bytes32 public immutable KEY; // solhint-disable-line var-name-mixedcase\n\n /// @dev string representation of feed key (feed name)\n string public description;\n\n /// @dev decimals for feed\n uint8 internal immutable _DECIMALS; // solhint-disable-line var-name-mixedcase\n\n error EmptyAddress();\n error FeedNotExist();\n\n /// @param _registry IRegistry address\n /// @param _umbrellaFeeds UmbrellaFeeds address\n /// @param _key price data key (before hashing)\n constructor(IRegistry _registry, IUmbrellaFeeds _umbrellaFeeds, string memory _key) {\n if (address(_registry) == address(0)) revert EmptyAddress();\n\n REGISTRY = _registry;\n UMBRELLA_FEEDS = address(_umbrellaFeeds);\n description = _key;\n _DECIMALS = _umbrellaFeeds.DECIMALS();\n\n bytes32 hash = keccak256(abi.encodePacked(_key));\n KEY = hash;\n\n // sanity check\n _umbrellaFeeds.getPriceData(hash);\n }\n\n /// @dev decimals for feed\n function decimals() external view returns (uint8) {\n return _DECIMALS;\n }\n\n /// @dev this method follows chainlink interface for easy migration, NOTE: not all returned data are covered!\n /// latestRoundData() raise exception when there is no data, instead of returning unset values,\n /// which could be misinterpreted as actual reported values.\n /// It DOES NOT raise when data is outdated (based on heartbeat and timestamp).\n /// @notice You can save some gas by doing call directly to `UMBRELLA_FEEDS` contract.\n /// @return uint80 originally `roundId`, not in use, always 0\n /// @return answer price\n /// @return uint256 originally `startedAt`, not in use, always 0\n /// @return updatedAt last timestamp data was updated\n /// @return uint80 originally `answeredInRound` not in use, always 0\n function latestRoundData()\n external\n view\n returns (\n uint80 /* roundId */,\n int256 answer,\n uint256 /* startedAt */,\n uint256 updatedAt,\n uint80 /* answeredInRound */\n )\n {\n IUmbrellaFeeds.PriceData memory priceData = _getPriceDataRaw();\n\n if (priceData.timestamp == 0) {\n priceData = _fallbackCall();\n }\n\n return (0, int256(uint256(priceData.price)), 0, priceData.timestamp, 0);\n }\n\n /// @dev this is main endpoint for reading feed. Feed is read from UmbrellaFeeds contract using hardcoded `KEY`.\n /// In case timestamp is empty (that means there is no data), contract will execute fallback call.\n /// @notice revert on empty data\n function getPriceData() external view returns (IUmbrellaFeeds.PriceData memory priceData) {\n priceData = _getPriceDataRaw();\n\n if (priceData.timestamp == 0) {\n priceData = _fallbackCall();\n }\n }\n\n /// @dev same as `getPriceData` but does not revert when no data\n function getPriceDataRaw() external view returns (IUmbrellaFeeds.PriceData memory priceData) {\n priceData = _getPriceDataRaw();\n\n if (priceData.timestamp == 0) {\n return _fallbackCallRaw();\n }\n }\n\n /// @dev same as `getPriceData` but does not revert when no data\n function _getPriceDataRaw() internal view returns (IUmbrellaFeeds.PriceData memory priceData) {\n (bool success, bytes memory data) = UMBRELLA_FEEDS.staticcall(\n abi.encodeWithSelector(IUmbrellaFeeds.prices.selector, KEY)\n );\n\n if (success && data.length != 0) {\n priceData = abi.decode(data, (IUmbrellaFeeds.PriceData));\n }\n }\n\n /// @dev it will revert on empty data\n function _fallbackCall() internal view returns (IUmbrellaFeeds.PriceData memory data) {\n address umbrellaFeeds = REGISTRY.getAddressByString(\"UmbrellaFeeds\");\n\n // if contract was NOT updated, fallback is not needed, data does not exist - revert\n if (umbrellaFeeds == UMBRELLA_FEEDS) revert FeedNotExist();\n\n data = IUmbrellaFeeds(umbrellaFeeds).getPriceData(KEY);\n }\n\n /// @dev it will not revert on empty data\n function _fallbackCallRaw() internal view returns (IUmbrellaFeeds.PriceData memory data) {\n address umbrellaFeeds = REGISTRY.getAddressByString(\"UmbrellaFeeds\");\n\n // if contract was updated, we do fallback\n if (umbrellaFeeds != UMBRELLA_FEEDS) {\n data = IUmbrellaFeeds(umbrellaFeeds).prices(KEY);\n }\n }\n}\n" + }, + "contracts/onChainFeeds/UmbrellaFeedsReaderFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\nimport \"./UmbrellaFeedsReader.sol\";\n\n/// @notice Factory to deploy UmbrellaFeedsReader contract\ncontract UmbrellaFeedsReaderFactory {\n /// @dev Registry contract where list of all addresses is stored. Used to resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev list of all readers\n mapping (bytes32 => UmbrellaFeedsReader) public readers;\n\n event NewUmbrellaFeedsReader(UmbrellaFeedsReader indexed umbrellaFeedsReader, string feedName);\n\n error EmptyAddress();\n\n constructor(IRegistry _registry) {\n if (address(_registry) == address(0)) revert EmptyAddress();\n\n REGISTRY = _registry;\n }\n\n /// @dev Method to deploy new UmbrellaFeedsReader for particular key.\n /// This deployment is optional and it can be done by anyone who needs it.\n /// Reader can be used to simplify migration from Chainlink to Umbrella.\n ///\n /// Check UmbrellaFeedsReader docs for more details.\n ///\n /// We not using minimal proxy because it does not allow for immutable variables.\n /// @param _feedName string Feed name that is registered in UmbrellaFeeds\n /// @return reader UmbrellaFeedsReader contract address, in case anyone wants to use it from Layer1\n function deploy(string memory _feedName) external returns (UmbrellaFeedsReader reader) {\n reader = deployed(_feedName);\n IUmbrellaFeeds umbrellaFeeds = IUmbrellaFeeds(REGISTRY.getAddressByString(\"UmbrellaFeeds\"));\n\n // if UmbrellaFeeds contract is up to date, there is no need to redeploy\n if (address(reader) != address(0) && address(reader.UMBRELLA_FEEDS()) == address(umbrellaFeeds)) {\n return reader;\n }\n\n reader = new UmbrellaFeedsReader(REGISTRY, umbrellaFeeds, _feedName);\n readers[hash(_feedName)] = reader;\n\n emit NewUmbrellaFeedsReader(reader, _feedName);\n }\n\n function deployed(string memory _feedName) public view returns (UmbrellaFeedsReader) {\n return readers[hash(_feedName)];\n }\n\n function hash(string memory _feedName) public pure returns (bytes32) {\n return keccak256(abi.encodePacked(_feedName));\n }\n\n /// @dev to follow Registrable interface\n function getName() public pure returns (bytes32) {\n return \"UmbrellaFeedsReaderFactory\";\n }\n}\n" + }, + "contracts/onChainFeeds/zk-link/UmbrellaFeeds.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../../interfaces/IUmbrellaFeeds.sol\";\nimport \"../../interfaces/IRegistry.sol\";\nimport \"../../interfaces/IStakingBankStatic.sol\";\n\n/// @dev Main contract for all on-chain data.\n/// Check `UmbrellaFeedsReader` to see how to integrate.\n///\n/// @notice This contract can be destroyed and replaced with new one (with new address).\n/// For best gas efficiency you should pick one of two ways of integration:\n/// 1. make `UmbrellaFeeds` immutable and use fallback in case of selfdestruct. After new deployment, it is recommended\n/// to update address to avoid fallback and reduce gas cost to minimum. In long run this is most efficient solution,\n/// better than any proxy.\n/// 2. always check newest `UmbrellaFeeds` via `Regostry` and fallback will not be needed.\ncontract UmbrellaFeeds is IUmbrellaFeeds {\n bytes constant public ETH_PREFIX = \"\\x19Ethereum Signed Message:\\n32\";\n string constant public NAME = \"UmbrellaFeeds\";\n\n /// @dev deployment time, used for protect for unintentional destroy\n uint256 public immutable DEPLOYED_AT; // solhint-disable-line var-name-mixedcase\n\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\n /// resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev StakingBank contract where list of validators is stored\n IStakingBankStatic public immutable STAKING_BANK; // solhint-disable-line var-name-mixedcase\n\n /// @dev minimal number of signatures required for accepting price submission (PoA)\n uint16 public immutable REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\n\n /// @dev decimals for prices stored in this contract\n uint8 public immutable DECIMALS; // solhint-disable-line var-name-mixedcase\n\n /// @dev in case selfdestruct is not supported, this flag will make sure contract is not usable anymore\n bool public disabled;\n\n /// @notice map of all prices stored in this contract, key for map is hash of feed name\n /// eg for \"ETH-USD\" feed, key will be hash(\"ETH-USD\")\n mapping (bytes32 => PriceData) private _prices;\n\n error SelfDestruct();\n error ArraysDataDoNotMatch();\n error FeedNotExist();\n error NotEnoughSignatures();\n error InvalidSigner();\n error InvalidRequiredSignatures();\n error SignaturesOutOfOrder();\n error ECDSAInvalidSignatureS();\n error ECDSAInvalidSignatureV();\n error OldData();\n error ContractInUse();\n error ContractNotInitialised();\n\n /// @param _contractRegistry Registry address\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n /// @param _decimals decimals for prices stored in this contract\n constructor(\n IRegistry _contractRegistry,\n uint16 _requiredSignatures,\n uint8 _decimals\n ) {\n if (_requiredSignatures == 0) revert InvalidRequiredSignatures();\n\n REGISTRY = _contractRegistry;\n REQUIRED_SIGNATURES = _requiredSignatures;\n STAKING_BANK = IStakingBankStatic(_contractRegistry.requireAndGetAddress(\"StakingBank\"));\n DECIMALS = _decimals;\n DEPLOYED_AT = block.timestamp;\n }\n\n /// @dev destroys old contract\n /// there is sanity check that prevents abuse of destroy method\n /// @param _name string feed key to verify, that contract was initialised\n function destroy(string calldata _name) external {\n if (REGISTRY.getAddressByString(NAME) == address(this)) revert ContractInUse();\n\n if (_prices[keccak256(abi.encodePacked(_name))].timestamp == 0 && DEPLOYED_AT + 3 days > block.timestamp) {\n revert ContractNotInitialised();\n }\n\n disabled = true;\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function update(\n bytes32[] calldata _priceKeys,\n PriceData[] calldata _priceDatas,\n Signature[] calldata _signatures\n ) external {\n if (disabled) revert SelfDestruct();\n if (_priceKeys.length != _priceDatas.length) revert ArraysDataDoNotMatch();\n\n bytes32 priceDataHash = keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n verifySignatures(priceDataHash, _signatures);\n\n uint256 i;\n\n while (i < _priceDatas.length) {\n bytes32 priceKey = _priceKeys[i];\n\n // we do not allow for older prices\n // at the same time it prevents from reusing signatures\n if (_prices[priceKey].timestamp >= _priceDatas[i].timestamp) revert OldData();\n\n _prices[priceKey] = _priceDatas[i];\n\n // atm there is no need for events, so in order to save gas, we do not emit any\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n if (disabled) revert SelfDestruct();\n\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n if (data[i].timestamp == 0) revert FeedNotExist();\n\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n if (disabled) revert SelfDestruct();\n\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function prices(bytes32 _key) external view returns (PriceData memory data) {\n if (disabled) revert SelfDestruct();\n\n data = _prices[_key];\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceData(bytes32 _key) external view returns (PriceData memory data) {\n if (disabled) revert SelfDestruct();\n\n data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPrice(bytes32 _key) external view returns (uint128 price) {\n if (disabled) revert SelfDestruct();\n\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return data.price;\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp) {\n if (disabled) revert SelfDestruct();\n\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp);\n }\n\n function getPriceTimestampHeartbeat(bytes32 _key)\n external\n view\n returns (uint128 price, uint32 timestamp, uint24 heartbeat)\n {\n if (disabled) revert SelfDestruct();\n\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp, data.heartbeat);\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data) {\n if (disabled) revert SelfDestruct();\n\n bytes32 key = keccak256(abi.encodePacked(_name));\n data = _prices[key];\n }\n\n /// @dev helper method for QA purposes\n /// @return hash of data that are signed by validators (keys and priced data)\n function hashData(bytes32[] calldata _priceKeys, PriceData[] calldata _priceDatas)\n external\n view\n returns (bytes32)\n {\n return keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n }\n\n /// @param _hash hash of signed data\n /// @param _signatures array of validators signatures\n function verifySignatures(bytes32 _hash, Signature[] calldata _signatures) public view {\n address prevSigner = address(0x0);\n\n if (_signatures.length < REQUIRED_SIGNATURES) revert NotEnoughSignatures();\n\n address[] memory validators = new address[](REQUIRED_SIGNATURES);\n\n // to save gas we check only required number of signatures\n // case, where you can have part of signatures invalid but still enough valid in total is not supported\n for (uint256 i; i < REQUIRED_SIGNATURES;) {\n (uint8 v, bytes32 r, bytes32 s) = (_signatures[i].v, _signatures[i].r, _signatures[i].s);\n\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n revert ECDSAInvalidSignatureS();\n }\n\n if (uint8(v) != 27 && uint8(v) != 28) revert ECDSAInvalidSignatureV();\n\n address signer = recoverSigner(_hash, v, r, s);\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\n\n // because we check only required number of signatures, any invalid one will cause revert\n prevSigner = signer;\n validators[i] = signer;\n\n unchecked { i++; }\n }\n\n // bulk verification can optimise gas when we have 5 or more validators\n if (!STAKING_BANK.verifyValidators(validators)) revert InvalidSigner();\n }\n\n function getChainId() public view returns (uint256 id) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n id := chainid()\n }\n }\n\n /// @param _hash hashed of data\n /// @param _v part of signature\n /// @param _r part of signature\n /// @param _s part of signature\n /// @return signer address\n function recoverSigner(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _hash));\n return ecrecover(hash, _v, _r, _s);\n }\n\n /// @dev to follow Registrable interface\n function getName() public pure returns (bytes32) {\n return \"UmbrellaFeeds\";\n }\n}\n" + }, + "contracts/Registry.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\n// Inheritance\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport \"./extensions/Registrable.sol\";\nimport \"./interfaces/IRegistry.sol\";\n\n/// @dev contracts registry\n/// protocol uses this registry to fetch current contract addresses\ncontract Registry is IRegistry, Ownable {\n /// name => contract address\n mapping(bytes32 => address) public registry;\n\n\n error NameNotRegistered();\n error ArraysDataDoNotMatch();\n\n /// @inheritdoc IRegistry\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external onlyOwner {\n if (_names.length != _destinations.length) revert ArraysDataDoNotMatch();\n\n for (uint i = 0; i < _names.length;) {\n registry[_names[i]] = _destinations[i];\n emit LogRegistered(_destinations[i], _names[i]);\n\n unchecked {\n i++;\n }\n }\n }\n\n /// @inheritdoc IRegistry\n function importContracts(address[] calldata _destinations) external onlyOwner {\n for (uint i = 0; i < _destinations.length;) {\n bytes32 name = Registrable(_destinations[i]).getName();\n registry[name] = _destinations[i];\n emit LogRegistered(_destinations[i], name);\n\n unchecked {\n i++;\n }\n }\n }\n\n /// @inheritdoc IRegistry\n function atomicUpdate(address _newContract) external onlyOwner {\n Registrable(_newContract).register();\n\n bytes32 name = Registrable(_newContract).getName();\n address oldContract = registry[name];\n registry[name] = _newContract;\n\n Registrable(oldContract).unregister();\n\n emit LogRegistered(_newContract, name);\n }\n\n /// @inheritdoc IRegistry\n function requireAndGetAddress(bytes32 name) external view returns (address) {\n address _foundAddress = registry[name];\n if (_foundAddress == address(0)) revert NameNotRegistered();\n\n return _foundAddress;\n }\n\n /// @inheritdoc IRegistry\n function getAddress(bytes32 _bytes) external view returns (address) {\n return registry[_bytes];\n }\n\n /// @inheritdoc IRegistry\n function getAddressByString(string memory _name) public view returns (address) {\n return registry[stringToBytes32(_name)];\n }\n\n /// @inheritdoc IRegistry\n function stringToBytes32(string memory _string) public pure returns (bytes32 result) {\n bytes memory tempEmptyStringTest = bytes(_string);\n\n if (tempEmptyStringTest.length == 0) {\n return 0x0;\n }\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n result := mload(add(_string, 32))\n }\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStatic.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/StakingBankStaticNotSupported.sol\";\n\n/// @dev Because we are using PoA in UMB oracle, staked balance does not matter. What's matter is, if signer is\n/// validator or not. In this case we can optimise `StakingBank` and make it static for better gas performance.\nabstract contract StakingBankStatic is StakingBankStaticNotSupported {\n uint256 public constant ONE = 1e18;\n\n uint256 public immutable NUMBER_OF_VALIDATORS; // solhint-disable-line var-name-mixedcase\n uint256 public immutable TOTAL_SUPPLY; // solhint-disable-line var-name-mixedcase\n\n constructor(uint256 _validatorsCount) {\n NUMBER_OF_VALIDATORS = _validatorsCount;\n TOTAL_SUPPLY = _validatorsCount * ONE;\n\n _assertValidSetup(_validatorsCount);\n }\n\n function balances(address _validator) external view returns (uint256) {\n return _isValidator(_validator) ? ONE : 0;\n }\n\n function verifyValidators(address[] calldata _validators) external view returns (bool) {\n for (uint256 i; i < _validators.length;) {\n if (!_isValidator(_validators[i])) return false;\n unchecked { i++; }\n }\n\n return true;\n }\n\n function getNumberOfValidators() external view returns (uint256) {\n return NUMBER_OF_VALIDATORS;\n }\n\n function getAddresses() external view returns (address[] memory) {\n return _addresses();\n }\n\n function getBalances() external view returns (uint256[] memory allBalances) {\n allBalances = new uint256[](NUMBER_OF_VALIDATORS);\n\n for (uint256 i; i < NUMBER_OF_VALIDATORS;) {\n allBalances[i] = ONE;\n\n unchecked {\n // we will not have enough data to overflow\n i++;\n }\n }\n }\n\n function addresses(uint256 _ix) external view returns (address) {\n return _addresses()[_ix];\n }\n\n function validators(address _id) external view virtual returns (address id, string memory location);\n\n /// @dev to follow ERC20 interface\n function balanceOf(address _account) external view returns (uint256) {\n return _isValidator(_account) ? ONE : 0;\n }\n\n /// @dev to follow ERC20 interface\n function totalSupply() external view returns (uint256) {\n return TOTAL_SUPPLY;\n }\n\n /// @dev to follow Registrable interface\n function getName() external pure returns (bytes32) {\n return \"StakingBank\";\n }\n\n /// @dev to follow Registrable interface\n function register() external pure {\n // there are no requirements atm\n }\n\n /// @dev to follow Registrable interface\n function unregister() external pure {\n // there are no requirements atm\n }\n\n function _addresses() internal view virtual returns (address[] memory);\n\n function _isValidator(address _validator) internal view virtual returns (bool);\n\n function _assertValidSetup(uint256 _validatorsCount) internal view virtual{\n address[] memory list = _addresses();\n require(list.length == _validatorsCount);\n\n for (uint256 i; i < _validatorsCount;) {\n require(_isValidator(list[i]));\n\n unchecked { i ++; }\n }\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticCI.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticCI is StakingBankStatic {\n // 0x87630b2d1de0fbd5044eb6891b3d9d98c34c8d310c852f98550ba774480e47cc\n address public constant VALIDATOR_0 = 0x2fFd013AaA7B5a7DA93336C2251075202b33FB2B;\n // 0x3f1e8b94c70206bf816c1ed0b15ad98bdf225ae4c6e7e4eee6cdbcf706fda2ae\n address public constant VALIDATOR_1 = 0x43158ea338Ff13D0bDa0c3EB969B9EA5a624E7Cc;\n // 0x5da6b84117504d06b5dcd52b990d76965d2882f4e5852eb610bc76e4209b10d7\n address public constant VALIDATOR_2 = 0x9Fd8DD0627b9A32399Fd115c4725C7e17BC40e6d;\n // 0x1e5012671de3332ad0b43661984e94ab0e405bffddc9d3e863055040bab354b8\n address public constant VALIDATOR_3 = 0xa3F3659E469b7aE0b249546338DEdc0b684edB05;\n // 0x0edc1e35ea7701ddac703286674e79f04addbf5d2f6162fabc19d39bd3dc6662\n address public constant VALIDATOR_4 = 0xB98A954B9036DF144d685E910bfbAEC6B33A8d11;\n // 0x23c601ae397441f3ef6f1075dcb0031ff17fb079837beadaf3c84d96c6f3e569\n address public constant VALIDATOR_5 = 0xE5904695748fe4A84b40b3fc79De2277660BD1D3;\n\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.ci.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.ci.umb.network\");\n if (_id == VALIDATOR_2) return (_id, \"https://validator3.ci.umb.network\");\n if (_id == VALIDATOR_3) return (_id, \"https://validator4.ci.umb.network\");\n if (_id == VALIDATOR_4) return (_id, \"https://validator5.ci.umb.network\");\n if (_id == VALIDATOR_5) return (_id, \"https://validator6.ci.umb.network\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n list[2] = VALIDATOR_2;\n list[3] = VALIDATOR_3;\n list[4] = VALIDATOR_4;\n list[5] = VALIDATOR_5;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0\n || _validator == VALIDATOR_1\n || _validator == VALIDATOR_2\n || _validator == VALIDATOR_3\n || _validator == VALIDATOR_4\n || _validator == VALIDATOR_5\n );\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticDev.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticDev is StakingBankStatic {\n address public constant VALIDATOR_0 = 0xDc3eBc37DA53A644D67E5E3b5BA4EEF88D969d5C;\n address public constant VALIDATOR_1 = 0x998cb7821e605cC16b6174e7C50E19ADb2Dd2fB0;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.dev.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.dev.umb.network\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0 || _validator == VALIDATOR_1);\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticLocal.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticLocal is StakingBankStatic {\n address public constant VALIDATOR_0 = 0xeAD9C93b79Ae7C1591b1FB5323BD777E86e150d4;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"localhost\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0);\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticProd.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\ncontract StakingBankStaticProd is StakingBankStatic {\n address public constant VALIDATOR_0 = 0x977Ba523420110e230643B772Fe9cF955e11dA7B;\n address public constant VALIDATOR_1 = 0xe2422b23e52bc13ebA04d7FbB9F332Deb43360fB;\n\n // external order is based on validators submits on AVAX for Apr 2023\n address public constant VALIDATOR_2 = 0x57F404aD75e371c1A539589C1eFCA12e0C6980AD;\n address public constant VALIDATOR_3 = 0xD56C6A4f64E0bD70260472d1DB6Cf5825858CB0d;\n address public constant VALIDATOR_4 = 0x93FdcAB283b0BcAc48157590af482E1CFd6af6aC;\n address public constant VALIDATOR_5 = 0xCd733E06B06083d52fC5867E8E3432aA5c103A38;\n address public constant VALIDATOR_6 = 0x42e210b110c6aa49CdfA7ceF1444Aa4719653111;\n address public constant VALIDATOR_7 = 0x501731c6a69803a53Ec6c3e12f293c247cE1092B;\n address public constant VALIDATOR_8 = 0x8bF9661F1b247522C75DD0FE84355aD2EfF27144;\n address public constant VALIDATOR_9 = 0x281754Ab58391A478B7aA4E7f39991CfB41118c4;\n address public constant VALIDATOR_10 = 0x57A51D5BDcE188c2295fCA3b4687475a54E65A02;\n address public constant VALIDATOR_11 = 0x2F85824B2B38F179E451988670935d315b5b9692;\n address public constant VALIDATOR_12 = 0xA7241994267682de4dE7Ef62f52dc2C783d1784B;\n address public constant VALIDATOR_13 = 0x6eEd457C20603EDAE50C3A112CAA1a9425321bD0;\n address public constant VALIDATOR_14 = 0xC5a7650c2725a7B6A39f15cb9FbffC7af357AFeb;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n // solhint-disable-next-line code-complexity\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.umb.network\");\n if (_id == VALIDATOR_2) return (_id, \"https://umbrella.artemahr.tech\");\n if (_id == VALIDATOR_3) return (_id, \"https://umb.vtabsolutions.com:3030\");\n if (_id == VALIDATOR_4) return (_id, \"https://umbrella.crazywhale.es\");\n if (_id == VALIDATOR_5) return (_id, \"https://umbrella-node.gateomega.com\");\n if (_id == VALIDATOR_6) return (_id, \"https://umb.anorak.technology\");\n if (_id == VALIDATOR_7) return (_id, \"https://umbrella.validator.infstones.io\");\n if (_id == VALIDATOR_8) return (_id, \"https://umb.hashkey.cloud\");\n if (_id == VALIDATOR_9) return (_id, \"http://umbrella.staking4all.org:3000\");\n if (_id == VALIDATOR_10) return (_id, \"http://5.161.78.230:3000\");\n if (_id == VALIDATOR_11) return (_id, \"https://umb-api.staking.rocks\");\n if (_id == VALIDATOR_12) return (_id, \"https://rpc.urbanhq.net\");\n if (_id == VALIDATOR_13) return (_id, \"https://umbrella-node.ankastake.com\");\n if (_id == VALIDATOR_14) return (_id, \"https://umbrella.tchambrella.com\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n list[2] = VALIDATOR_2;\n list[3] = VALIDATOR_3;\n list[4] = VALIDATOR_4;\n list[5] = VALIDATOR_5;\n list[6] = VALIDATOR_6;\n list[7] = VALIDATOR_7;\n list[8] = VALIDATOR_8;\n list[9] = VALIDATOR_9;\n list[10] = VALIDATOR_10;\n list[11] = VALIDATOR_11;\n list[12] = VALIDATOR_12;\n list[13] = VALIDATOR_13;\n list[14] = VALIDATOR_14;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (\n _validator == VALIDATOR_0\n || _validator == VALIDATOR_1\n || _validator == VALIDATOR_2\n || _validator == VALIDATOR_3\n || _validator == VALIDATOR_4\n || _validator == VALIDATOR_5\n || _validator == VALIDATOR_6\n || _validator == VALIDATOR_7\n || _validator == VALIDATOR_8\n || _validator == VALIDATOR_9\n || _validator == VALIDATOR_10\n || _validator == VALIDATOR_11\n || _validator == VALIDATOR_12\n || _validator == VALIDATOR_13\n || _validator == VALIDATOR_14\n );\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticSbx.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticSbx is StakingBankStatic {\n address public constant VALIDATOR_0 = 0xE3bDa0C6E1fBB111091Dfef6f22a673b20Ea5F50;\n address public constant VALIDATOR_1 = 0xc1773490F00963CBAb3841fc07C1a0796E658Ba2;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.sbx.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.sbx.umb.network\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0 || _validator == VALIDATOR_1);\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": false, + "runs": 0 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/polygon_production/ForeignChain.json b/deployments/polygon_production/ForeignChain.json index 396fb6bc..02aea59d 100644 --- a/deployments/polygon_production/ForeignChain.json +++ b/deployments/polygon_production/ForeignChain.json @@ -1,5 +1,5 @@ { - "address": "0x3f7D481DC7156a79a49b57Cf5466dBA9FfB0e8Ca", + "address": "0x225867a24c167478773ee0F007b784E6d5ECADE6", "abi": [ { "inputs": [ @@ -1051,48 +1051,48 @@ "type": "function" } ], - "transactionHash": "0x95972dcd58c87273af2b5b062f66de57869ca21a85ff54c035a9cd0c17c95910", + "transactionHash": "0xe0e6948dbf1320c0ba6ef123440cfb61020eed86c78b5c7b896ad583d459b8f8", "receipt": { "to": null, "from": "0xA6e4fFa19B213AbeA258ae72e8e1a209B9E543e7", - "contractAddress": "0x3f7D481DC7156a79a49b57Cf5466dBA9FfB0e8Ca", - "transactionIndex": 58, - "gasUsed": "4443993", - "logsBloom": "0x00000000000000000000000000000000000000000000000000800000400000000000000000000000000000000002000000008000000000000000000000000000000800040000000000000000000000800001000000000000000100000000000000000000020000000000000000000800000000000000000080000000000020400000000000000000000000000000000000000000000000040002000000000000200000000000004000000000000000000000000000000000010000000000004400000000000000000001000000000000000020000000000000100000000020000000000000000000000100000000000000000000000000000000000000100000", - "blockHash": "0x07f5a5b868d9fce74114c537a532049dd41840fd6f9695f785139ebfb11a4551", - "transactionHash": "0x95972dcd58c87273af2b5b062f66de57869ca21a85ff54c035a9cd0c17c95910", + "contractAddress": "0x225867a24c167478773ee0F007b784E6d5ECADE6", + "transactionIndex": 54, + "gasUsed": "4445409", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000400000000000000000000000000000000002000000008000000000000000000000000000000000000800000000000000000000800001000000400000000100000000000000000000020000000000000000000800000000000000000080000000000020400000000000000000000000000000000000000000000000040002000000000000200000000000004000000000000000000000000000000000010000000000004400000000000000000001000000000000000020000000000000100000000020000000000000000000000000000000000000000000000000000000000000100000", + "blockHash": "0x8574fdba704dccde45f3b2304a92fbe21e7c8ff9d0f00104ba872c8d0b70c432", + "transactionHash": "0xe0e6948dbf1320c0ba6ef123440cfb61020eed86c78b5c7b896ad583d459b8f8", "logs": [ { - "transactionIndex": 58, - "blockNumber": 49650366, - "transactionHash": "0x95972dcd58c87273af2b5b062f66de57869ca21a85ff54c035a9cd0c17c95910", - "address": "0x3f7D481DC7156a79a49b57Cf5466dBA9FfB0e8Ca", + "transactionIndex": 54, + "blockNumber": 63724222, + "transactionHash": "0xe0e6948dbf1320c0ba6ef123440cfb61020eed86c78b5c7b896ad583d459b8f8", + "address": "0x225867a24c167478773ee0F007b784E6d5ECADE6", "topics": [ "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x000000000000000000000000a6e4ffa19b213abea258ae72e8e1a209b9e543e7" ], "data": "0x", - "logIndex": 223, - "blockHash": "0x07f5a5b868d9fce74114c537a532049dd41840fd6f9695f785139ebfb11a4551" + "logIndex": 528, + "blockHash": "0x8574fdba704dccde45f3b2304a92fbe21e7c8ff9d0f00104ba872c8d0b70c432" }, { - "transactionIndex": 58, - "blockNumber": 49650366, - "transactionHash": "0x95972dcd58c87273af2b5b062f66de57869ca21a85ff54c035a9cd0c17c95910", - "address": "0x3f7D481DC7156a79a49b57Cf5466dBA9FfB0e8Ca", + "transactionIndex": 54, + "blockNumber": 63724222, + "transactionHash": "0xe0e6948dbf1320c0ba6ef123440cfb61020eed86c78b5c7b896ad583d459b8f8", + "address": "0x225867a24c167478773ee0F007b784E6d5ECADE6", "topics": [ "0x02ff77a0f68d11f7efb906f331b2dda82916de8ba9c37dda2a95817936a530ec", "0x000000000000000000000000a6e4ffa19b213abea258ae72e8e1a209b9e543e7" ], "data": "0x00000000000000000000000000000000000000000000000000000000000000b4", - "logIndex": 224, - "blockHash": "0x07f5a5b868d9fce74114c537a532049dd41840fd6f9695f785139ebfb11a4551" + "logIndex": 529, + "blockHash": "0x8574fdba704dccde45f3b2304a92fbe21e7c8ff9d0f00104ba872c8d0b70c432" }, { - "transactionIndex": 58, - "blockNumber": 49650366, - "transactionHash": "0x95972dcd58c87273af2b5b062f66de57869ca21a85ff54c035a9cd0c17c95910", + "transactionIndex": 54, + "blockNumber": 63724222, + "transactionHash": "0xe0e6948dbf1320c0ba6ef123440cfb61020eed86c78b5c7b896ad583d459b8f8", "address": "0x0000000000000000000000000000000000001010", "topics": [ "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63", @@ -1100,13 +1100,13 @@ "0x000000000000000000000000a6e4ffa19b213abea258ae72e8e1a209b9e543e7", "0x000000000000000000000000a8b52f02108aa5f4b675bdcc973760022d7c6020" ], - "data": "0x00000000000000000000000000000000000000000000000002232d84ae4a2ed1000000000000000000000000000000000000000000000000af9245e8c23837030000000000000000000000000000000000000000000000768cdd58b9816743dc000000000000000000000000000000000000000000000000ad6f186413ee08320000000000000000000000000000000000000000000000768f00863e2fb172ad", - "logIndex": 225, - "blockHash": "0x07f5a5b868d9fce74114c537a532049dd41840fd6f9695f785139ebfb11a4551" + "data": "0x0000000000000000000000000000000000000000000000000232d5a164a3add10000000000000000000000000000000000000000000000003ae129494f3761620000000000000000000000000000000000000000000000ad5ae200a46f080cc300000000000000000000000000000000000000000000000038ae53a7ea93b3910000000000000000000000000000000000000000000000ad5d14d645d3abba94", + "logIndex": 530, + "blockHash": "0x8574fdba704dccde45f3b2304a92fbe21e7c8ff9d0f00104ba872c8d0b70c432" } ], - "blockNumber": 49650366, - "cumulativeGasUsed": "12896506", + "blockNumber": 63724222, + "cumulativeGasUsed": "18434706", "status": 1, "byzantium": true }, @@ -1117,7 +1117,7 @@ false ], "numDeployments": 1, - "solcInputHash": "4db3e1d3dd51dbe508dc0a6a04352df6", + "solcInputHash": "dc68422c0ad35a4fe46d461b096b9383", "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"_contractRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"_padding\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"_requiredSignatures\",\"type\":\"uint16\"},{\"internalType\":\"bool\",\"name\":\"_allowForMixedType\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyDeprecated\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArraysDataDoNotMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BlockSubmittedToFastOrDataToOld\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractNotReady\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FCDOverflow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContractType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoChangeToState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotEnoughSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotSupported\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyOwnerOrRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfOrder\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnregisterFirst\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"deprecator\",\"type\":\"address\"}],\"name\":\"LogDeprecation\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"blockId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"staked\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"power\",\"type\":\"uint256\"}],\"name\":\"LogMint\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"executor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"timePadding\",\"type\":\"uint32\"}],\"name\":\"LogPadding\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"blockId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"vote\",\"type\":\"uint256\"}],\"name\":\"LogVoter\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ETH_PREFIX\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_blockId\",\"type\":\"uint256\"}],\"name\":\"blocks\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"dataTimestamp\",\"type\":\"uint32\"}],\"internalType\":\"struct BaseChain.Block\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blocksCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blocksCountOffset\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_offset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_items\",\"type\":\"uint256\"}],\"name\":\"bytesToBytes32Array\",\"outputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"contractRegistry\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deprecate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"fcds\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"dataTimestamp\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockId\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"getBlockIdAtTimestamp\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_blockId\",\"type\":\"uint32\"}],\"name\":\"getBlockRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_blockId\",\"type\":\"uint32\"}],\"name\":\"getBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConsensusData\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"blocksCountOffset\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"sequence\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"lastTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"padding\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"deprecated\",\"type\":\"bool\"}],\"internalType\":\"struct BaseChain.ConsensusData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getCurrentIntValue\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"value\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getCurrentValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_keys\",\"type\":\"bytes32[]\"}],\"name\":\"getCurrentValues\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"uint32[]\",\"name\":\"timestamps\",\"type\":\"uint32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestBlockId\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLeaderAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"getLeaderAddressAtTime\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"getLeaderIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNextLeaderAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStatus\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"timePadding\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"lastDataTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"lastId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"nextLeader\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"nextBlockId\",\"type\":\"uint32\"},{\"internalType\":\"address[]\",\"name\":\"validators\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"powers\",\"type\":\"uint256[]\"},{\"internalType\":\"string[]\",\"name\":\"locations\",\"type\":\"string[]\"},{\"internalType\":\"uint256\",\"name\":\"staked\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"minSignatures\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_key\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_value\",\"type\":\"bytes\"}],\"name\":\"hashLeaf\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isForeign\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastBlockId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_affidavit\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"_v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"_r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_s\",\"type\":\"bytes32\"}],\"name\":\"recoverSigner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"register\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"requiredSignatures\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"roots\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"_padding\",\"type\":\"uint16\"}],\"name\":\"setPadding\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stakingBank\",\"outputs\":[{\"internalType\":\"contract IStakingBank\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stakingBankContract\",\"outputs\":[{\"internalType\":\"contract IStakingBank\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_dataTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"_root\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"_keys\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_values\",\"type\":\"uint256[]\"},{\"internalType\":\"uint8[]\",\"name\":\"_v\",\"type\":\"uint8[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"_r\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"_s\",\"type\":\"bytes32[]\"}],\"name\":\"submit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"tokenContract\",\"outputs\":[{\"internalType\":\"contract ERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_proof\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"_root\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_leaf\",\"type\":\"bytes32\"}],\"name\":\"verifyProof\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_blockId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"_proof\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"_key\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_value\",\"type\":\"bytes\"}],\"name\":\"verifyProofForBlock\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"_blockIds\",\"type\":\"uint32[]\"},{\"internalType\":\"bytes\",\"name\":\"_proofs\",\"type\":\"bytes\"},{\"internalType\":\"uint256[]\",\"name\":\"_proofItemsCounter\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"_leaves\",\"type\":\"bytes32[]\"}],\"name\":\"verifyProofs\",\"outputs\":[{\"internalType\":\"bool[]\",\"name\":\"results\",\"type\":\"bool[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"contract for foreign chains\",\"kind\":\"dev\",\"methods\":{\"blocks(uint256)\":{\"params\":{\"_blockId\":\"ID of submitted block\"},\"returns\":{\"_0\":\"block data (root + timestamp)\"}},\"blocksCount()\":{\"details\":\"number of blocks (consensus rounds) saved in this contract\"},\"bytesToBytes32Array(bytes,uint256,uint256)\":{\"details\":\"this is helper method, that extracts one merkle proof from many hashed provided as bytes\",\"params\":{\"_data\":\"many hashes as bytes\",\"_items\":\"how many hashes to extract\",\"_offset\":\"this is starting point for extraction\"},\"returns\":{\"_0\":\"merkle proof (array of bytes32 hashes)\"}},\"constructor\":{\"params\":{\"_contractRegistry\":\"Registry address\",\"_padding\":\"required \\\"space\\\" between blocks in seconds\",\"_requiredSignatures\":\"number of required signatures for accepting consensus submission\"}},\"getBlockId()\":{\"returns\":{\"_0\":\"current block ID please note, that current ID is not the same as last ID, current means that once padding pass, ID will switch to next one and it will be pointing to empty submit until submit for that ID is done\"}},\"getBlockIdAtTimestamp(uint256)\":{\"details\":\"calculates block ID for provided timestamp this function does not works for past timestamps\",\"params\":{\"_timestamp\":\"current or future timestamp\"},\"returns\":{\"_0\":\"block ID for provided timestamp\"}},\"getBlockRoot(uint32)\":{\"params\":{\"_blockId\":\"consensus ID\"},\"returns\":{\"_0\":\"root for provided consensus ID\"}},\"getBlockTimestamp(uint32)\":{\"params\":{\"_blockId\":\"consensus ID\"},\"returns\":{\"_0\":\"timestamp for provided consensus ID\"}},\"getConsensusData()\":{\"details\":\"getter for `_consensusData`\"},\"getCurrentIntValue(bytes32)\":{\"details\":\"getter for single FCD value in case its type is `int`\",\"params\":{\"_key\":\"FCD key\"},\"returns\":{\"timestamp\":\"FCD timestamp\",\"value\":\"FCD value\"}},\"getCurrentValue(bytes32)\":{\"details\":\"getter for single FCD value\",\"params\":{\"_key\":\"FCD key\"},\"returns\":{\"timestamp\":\"FCD timestamp\",\"value\":\"FCD value\"}},\"getCurrentValues(bytes32[])\":{\"details\":\"batch getter for FCDs\",\"params\":{\"_keys\":\"FCDs keys to fetch\"},\"returns\":{\"timestamps\":\"array of FCDs timestamps\",\"values\":\"array of FCDs values\"}},\"getLatestBlockId()\":{\"returns\":{\"_0\":\"last submitted block ID, please note, that on deployment, when there is no submission for this contract block for last ID will be available in previous contract\"}},\"getLeaderAddress()\":{\"returns\":{\"_0\":\"address of current leader\"}},\"getName()\":{\"returns\":{\"_0\":\"contract name as bytes32\"}},\"getNextLeaderAddress()\":{\"returns\":{\"_0\":\"address of leader for next second\"}},\"getStatus()\":{\"details\":\"helper method that returns all important data about current state of contract\",\"returns\":{\"blockNumber\":\"`block.number`\",\"lastDataTimestamp\":\"timestamp for last submitted consensus\",\"lastId\":\"ID of last submitted consensus\",\"locations\":\"array will be always empty\",\"minSignatures\":\"`this.requiredSignatures`\",\"nextBlockId\":\"block ID for `block.timestamp + padding`\",\"nextLeader\":\"will be always address(0)\",\"powers\":\"array will be always empty\",\"staked\":\"total UMB staked by validators\",\"timePadding\":\"`this.padding`\",\"validators\":\"array will be always empty\"}},\"hashLeaf(bytes,bytes)\":{\"details\":\"creates leaf hash, that has is used in merkle tree\",\"params\":{\"_key\":\"key under which we store the value\",\"_value\":\"value itself as bytes\"},\"returns\":{\"_0\":\"leaf hash\"}},\"isForeign()\":{\"returns\":{\"_0\":\"TRUE if contract is ForeignChain, FALSE otherwise\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"recoverSigner(bytes32,uint8,bytes32,bytes32)\":{\"params\":{\"_affidavit\":\"root and FCDs hashed together\",\"_r\":\"part of signature\",\"_s\":\"part of signature\",\"_v\":\"part of signature\"},\"returns\":{\"_0\":\"signer address\"}},\"register()\":{\"details\":\"this method will be called as a first method in registration process when old contract will be replaced when called, old contract address is still in registry\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setPadding(uint16)\":{\"details\":\"setter for `padding`\"},\"stakingBankContract()\":{\"details\":\"helper method for fetching StakingBank address\"},\"submit(uint32,bytes32,bytes32[],uint256[],uint8[],bytes32[],bytes32[])\":{\"details\":\"method for submitting consensus data\",\"params\":{\"_dataTimestamp\":\"consensus timestamp, this is time for all data in merkle tree including FCDs\",\"_keys\":\"FCDs keys\",\"_r\":\"array of `r` part of validators signatures\",\"_root\":\"merkle root\",\"_s\":\"array of `s` part of validators signatures\",\"_v\":\"array of `v` part of validators signatures\",\"_values\":\"FCDs values\"}},\"tokenContract()\":{\"details\":\"helper method for fetching UMB address\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"unregister()\":{\"details\":\"this method will be called as a last method in registration process when old contract will be replaced when called, new contract address is already in registry\"},\"verifyProof(bytes32[],bytes32,bytes32)\":{\"details\":\"verifies if the leaf is valid leaf for merkle tree\",\"params\":{\"_leaf\":\"leaf hash\",\"_proof\":\"merkle proof for merkle tree\",\"_root\":\"merkle root\"},\"returns\":{\"_0\":\"TRUE if `_leaf` is valid, FALSE otherwise\"}},\"verifyProofForBlock(uint256,bytes32[],bytes,bytes)\":{\"details\":\"verifies, if provided key-value pair was part of consensus\",\"params\":{\"_blockId\":\"consensus ID for which we doing a check\",\"_key\":\"pair key\",\"_proof\":\"merkle proof for pair\",\"_value\":\"pair value\"},\"returns\":{\"_0\":\"TRUE if key-value par was part of consensus, FALSE otherwise\"}},\"verifyProofs(uint32[],bytes,uint256[],bytes32[])\":{\"details\":\"batch method for data verification\",\"params\":{\"_blockIds\":\"consensus IDs for which we doing a checks\",\"_leaves\":\"array of merkle leaves\",\"_proofItemsCounter\":\"array of counters, each counter tells how many hashes proof for each leaf has\",\"_proofs\":\"merkle proofs for all pair, sequence of hashes provided as bytes\"},\"returns\":{\"results\":\"array of verification results, TRUE if leaf is part of consensus, FALSE otherwise\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"deprecate()\":{\"notice\":\"it allows to deprecate contract manually Only new Registry calls `unregister()` where we set deprecated to true In old Registries we don't have this feature, so in order to safely redeploy new Chain we will have to first deprecate current contract manually, then register new contract\"},\"getStatus()\":{\"notice\":\"this method is made to be compatible with MasterChain, but it does not return full data eg validators data will be missing.\"},\"register()\":{\"notice\":\"if this method needs to be called manually (not from Registry) it is important to do it as part of tx batch eg using multisig, we should prepare set of transactions and confirm them all at once\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/ForeignChain.sol\":\"ForeignChain\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":0},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0x24e0364e503a9bbde94c715d26573a76f14cd2a202d45f96f52134ab806b67b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\\n * instead returning `false` on failure. This behavior is nonetheless\\n * conventional and does not conflict with the expectations of ERC20\\n * applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * The default value of {decimals} is 18. To select a different value for\\n * {decimals} you should overload it.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n * overridden;\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\\n * `transferFrom`. This is semantically equivalent to an infinite approval.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * NOTE: Does not update the allowance if the current allowance\\n * is the maximum `uint256`.\\n *\\n * Requirements:\\n *\\n * - `from` and `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) public virtual override returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, amount);\\n _transfer(from, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, allowance(owner, spender) + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n uint256 currentAllowance = allowance(owner, spender);\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n */\\n function _transfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {\\n require(from != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(to != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, amount);\\n\\n uint256 fromBalance = _balances[from];\\n require(fromBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[from] = fromBalance - amount;\\n }\\n _balances[to] += amount;\\n\\n emit Transfer(from, to, amount);\\n\\n _afterTokenTransfer(from, to, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n _balances[account] += amount;\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n }\\n _totalSupply -= amount;\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(\\n address owner,\\n address spender,\\n uint256 amount\\n ) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\\n *\\n * Does not update the allowance amount in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Might emit an {Approval} event.\\n */\\n function _spendAllowance(\\n address owner,\\n address spender,\\n uint256 amount\\n ) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance != type(uint256).max) {\\n require(currentAllowance >= amount, \\\"ERC20: insufficient allowance\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - amount);\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {}\\n}\\n\",\"keccak256\":\"0xe0c8b625a79bac0fe80f17cfb521e072805cc9cef1c96a5caf45b264e74812fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/cryptography/MerkleProof.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev These functions deal with verification of Merkle Trees proofs.\\n *\\n * The proofs can be generated using the JavaScript library\\n * https://github.com/miguelmota/merkletreejs[merkletreejs].\\n * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.\\n *\\n * See `test/utils/cryptography/MerkleProof.test.js` for some examples.\\n *\\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\\n * hashing, or use a hash function other than keccak256 for hashing leaves.\\n * This is because the concatenation of a sorted pair of internal nodes in\\n * the merkle tree could be reinterpreted as a leaf value.\\n */\\nlibrary MerkleProof {\\n /**\\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\\n * defined by `root`. For this, a `proof` must be provided, containing\\n * sibling hashes on the branch from the leaf to the root of the tree. Each\\n * pair of leaves and each pair of pre-images are assumed to be sorted.\\n */\\n function verify(\\n bytes32[] memory proof,\\n bytes32 root,\\n bytes32 leaf\\n ) internal pure returns (bool) {\\n return processProof(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\\n * hash matches the root of the tree. When processing the proof, the pairs\\n * of leafs & pre-images are assumed to be sorted.\\n *\\n * _Available since v4.4._\\n */\\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n bytes32 proofElement = proof[i];\\n if (computedHash <= proofElement) {\\n // Hash(current computed hash + current element of the proof)\\n computedHash = _efficientHash(computedHash, proofElement);\\n } else {\\n // Hash(current element of the proof + current computed hash)\\n computedHash = _efficientHash(proofElement, computedHash);\\n }\\n }\\n return computedHash;\\n }\\n\\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\\n assembly {\\n mstore(0x00, a)\\n mstore(0x20, b)\\n value := keccak256(0x00, 0x40)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaaa504ac17eb0298dcdf5733ce24021b4914f035b97f4400b92827341d3facb3\",\"license\":\"MIT\"},\"@umb-network/toolbox/dist/contracts/lib/ValueDecoder.sol\":{\"content\":\"//SPDX-License-Identifier: Unlicensed\\npragma solidity >=0.6.8;\\n\\nlibrary ValueDecoder {\\n function toUint(bytes memory _bytes) internal pure returns (uint256 value) {\\n assembly {\\n value := mload(add(_bytes, 32))\\n }\\n }\\n\\n function toUint(bytes32 _bytes) internal pure returns (uint256 value) {\\n assembly {\\n value := _bytes\\n }\\n }\\n\\n function toInt(uint224 u) internal pure returns (int256) {\\n int224 i;\\n uint224 max = type(uint224).max;\\n\\n if (u <= (max - 1) / 2) { // positive values\\n assembly {\\n i := add(u, 0)\\n }\\n\\n return i;\\n } else { // negative values\\n assembly {\\n i := sub(sub(u, max), 1)\\n }\\n }\\n\\n return i;\\n }\\n}\\n\\n\",\"keccak256\":\"0x4c27669880111dd724930e6e2cb0baefdb3a8b7b2d6ffc0ec5c5534bc678a852\",\"license\":\"Unlicensed\"},\"contracts/BaseChain.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\\\";\\nimport \\\"@umb-network/toolbox/dist/contracts/lib/ValueDecoder.sol\\\";\\n\\nimport \\\"./interfaces/IBaseChainV1.sol\\\";\\nimport \\\"./interfaces/IStakingBank.sol\\\";\\nimport \\\"./extensions/Registrable.sol\\\";\\nimport \\\"./Registry.sol\\\";\\n\\nabstract contract BaseChain is Registrable, Ownable {\\n using ValueDecoder for bytes;\\n using ValueDecoder for uint224;\\n using MerkleProof for bytes32[];\\n\\n /// @param root merkle root for consensus\\n /// @param dataTimestamp consensus timestamp\\n struct Block {\\n bytes32 root;\\n uint32 dataTimestamp;\\n }\\n\\n /// @param value FCD value\\n /// @param dataTimestamp FCD timestamp\\n struct FirstClassData {\\n uint224 value;\\n uint32 dataTimestamp;\\n }\\n\\n /// @param blocksCountOffset number of all blocks that were generated before switching to this contract\\n /// @param sequence is a total number of blocks (consensus rounds) including previous contracts\\n /// @param lastTimestamp is a timestamp of last submitted block\\n /// @param padding number of seconds that need to pass before new submit will be possible\\n /// @param deprecated flag that changes to TRUE on `unregister`, when TRUE submissions are not longer available\\n struct ConsensusData {\\n uint32 blocksCountOffset;\\n uint32 sequence;\\n uint32 lastTimestamp;\\n uint32 padding;\\n bool deprecated;\\n }\\n\\n uint256 constant public VERSION = 2;\\n\\n bool internal immutable _ALLOW_FOR_MIXED_TYPE; // solhint-disable-line var-name-mixedcase\\n\\n bytes4 constant private _VERSION_SELECTOR = bytes4(keccak256(\\\"VERSION()\\\"));\\n\\n /// @dev minimal number of signatures required for accepting submission (PoA)\\n uint16 internal immutable _REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\\n\\n ConsensusData internal _consensusData;\\n\\n bytes constant public ETH_PREFIX = \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\";\\n\\n /// @dev block id (consensus ID) => root\\n /// consensus ID is at the same time consensus timestamp\\n mapping(uint256 => bytes32) public roots;\\n\\n /// @dev FCD key => FCD data\\n mapping(bytes32 => FirstClassData) public fcds;\\n\\n event LogDeprecation(address indexed deprecator);\\n event LogPadding(address indexed executor, uint32 timePadding);\\n\\n error ArraysDataDoNotMatch();\\n error AlreadyDeprecated();\\n error AlreadyRegistered();\\n error BlockSubmittedToFastOrDataToOld();\\n error ContractNotReady();\\n error FCDOverflow();\\n error InvalidContractType();\\n error NoChangeToState();\\n error OnlyOwnerOrRegistry();\\n error UnregisterFirst();\\n\\n modifier onlyOwnerOrRegistry () {\\n if (msg.sender != address(contractRegistry) && msg.sender != owner()) revert OnlyOwnerOrRegistry();\\n _;\\n }\\n\\n /// @param _contractRegistry Registry address\\n /// @param _padding required \\\"space\\\" between blocks in seconds\\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\\n constructor(\\n IRegistry _contractRegistry,\\n uint32 _padding,\\n uint16 _requiredSignatures,\\n bool _allowForMixedType\\n ) Registrable(_contractRegistry) {\\n _ALLOW_FOR_MIXED_TYPE = _allowForMixedType;\\n _REQUIRED_SIGNATURES = _requiredSignatures;\\n\\n _setPadding(_padding);\\n\\n BaseChain oldChain = BaseChain(_contractRegistry.getAddress(\\\"Chain\\\"));\\n\\n if (address(oldChain) == address(0)) {\\n // if this is first contract in sidechain, then we need to initialise lastTimestamp so submission\\n // can be possible\\n _consensusData.lastTimestamp = uint32(block.timestamp) - _padding - 1;\\n }\\n }\\n\\n /// @dev setter for `padding`\\n function setPadding(uint16 _padding) external {\\n _setPadding(_padding);\\n }\\n\\n /// @notice if this method needs to be called manually (not from Registry)\\n /// it is important to do it as part of tx batch\\n /// eg using multisig, we should prepare set of transactions and confirm them all at once\\n /// @inheritdoc Registrable\\n function register() external override onlyOwnerOrRegistry {\\n address oldChain = contractRegistry.getAddress(\\\"Chain\\\");\\n\\n // registration must be done before address in registry is replaced\\n if (oldChain == address(this)) revert AlreadyRegistered();\\n\\n if (oldChain == address(0x0)) {\\n return;\\n }\\n\\n _cloneLastDataFromPrevChain(oldChain);\\n }\\n\\n /// @inheritdoc Registrable\\n function unregister() external override onlyOwnerOrRegistry {\\n // in case we deprecated contract manually, we simply return\\n if (_consensusData.deprecated) return;\\n\\n address newChain = contractRegistry.getAddress(\\\"Chain\\\");\\n // unregistering must be done after address in registry is replaced\\n if (newChain == address(this)) revert UnregisterFirst();\\n\\n // TODO:\\n // I think we need to remove restriction for type (at least once)\\n // when we will switch to multichain architecture\\n\\n if (!_ALLOW_FOR_MIXED_TYPE) {\\n // can not be replaced with chain of different type\\n if (BaseChain(newChain).isForeign() != this.isForeign()) revert InvalidContractType();\\n }\\n\\n _consensusData.deprecated = true;\\n emit LogDeprecation(msg.sender);\\n }\\n\\n /// @notice it allows to deprecate contract manually\\n /// Only new Registry calls `unregister()` where we set deprecated to true\\n /// In old Registries we don't have this feature, so in order to safely redeploy new Chain\\n /// we will have to first deprecate current contract manually, then register new contract\\n function deprecate() external onlyOwnerOrRegistry {\\n if (_consensusData.deprecated) revert AlreadyDeprecated();\\n\\n _consensusData.deprecated = true;\\n emit LogDeprecation(msg.sender);\\n }\\n\\n /// @dev getter for `_consensusData`\\n function getConsensusData() external view returns (ConsensusData memory) {\\n return _consensusData;\\n }\\n\\n /// @dev number of blocks (consensus rounds) saved in this contract\\n function blocksCount() external view returns (uint256) {\\n return _consensusData.sequence - _consensusData.blocksCountOffset;\\n }\\n\\n function blocksCountOffset() external view returns (uint32) {\\n return _consensusData.blocksCountOffset;\\n }\\n\\n function lastBlockId() external view returns (uint256) {\\n return _consensusData.lastTimestamp;\\n }\\n\\n /// @return TRUE if contract is ForeignChain, FALSE otherwise\\n function isForeign() external pure virtual returns (bool);\\n\\n /// @inheritdoc Registrable\\n function getName() external pure override returns (bytes32) {\\n return \\\"Chain\\\";\\n }\\n\\n /// @param _affidavit root and FCDs hashed together\\n /// @param _v part of signature\\n /// @param _r part of signature\\n /// @param _s part of signature\\n /// @return signer address\\n function recoverSigner(bytes32 _affidavit, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _affidavit));\\n return ecrecover(hash, _v, _r, _s);\\n }\\n\\n /// @param _blockId ID of submitted block\\n /// @return block data (root + timestamp)\\n function blocks(uint256 _blockId) external view returns (Block memory) {\\n return Block(roots[_blockId], uint32(_blockId));\\n }\\n\\n /// @return current block ID\\n /// please note, that current ID is not the same as last ID, current means that once padding pass,\\n /// ID will switch to next one and it will be pointing to empty submit until submit for that ID is done\\n function getBlockId() external view returns (uint32) {\\n if (_consensusData.lastTimestamp == 0) return 0;\\n\\n return getBlockIdAtTimestamp(block.timestamp);\\n }\\n\\n function requiredSignatures() external view returns (uint16) {\\n return _REQUIRED_SIGNATURES;\\n }\\n\\n /// @dev calculates block ID for provided timestamp\\n /// this function does not works for past timestamps\\n /// @param _timestamp current or future timestamp\\n /// @return block ID for provided timestamp\\n function getBlockIdAtTimestamp(uint256 _timestamp) virtual public view returns (uint32) {\\n ConsensusData memory data = _consensusData;\\n\\n unchecked {\\n // we can't overflow because we adding two `uint32`\\n if (data.lastTimestamp + data.padding < _timestamp) {\\n return uint32(_timestamp);\\n }\\n }\\n\\n return data.lastTimestamp;\\n }\\n\\n /// @return last submitted block ID, please note, that on deployment, when there is no submission for this contract\\n /// block for last ID will be available in previous contract\\n function getLatestBlockId() virtual public view returns (uint32) {\\n return _consensusData.lastTimestamp;\\n }\\n\\n /// @dev verifies if the leaf is valid leaf for merkle tree\\n /// @param _proof merkle proof for merkle tree\\n /// @param _root merkle root\\n /// @param _leaf leaf hash\\n /// @return TRUE if `_leaf` is valid, FALSE otherwise\\n function verifyProof(bytes32[] memory _proof, bytes32 _root, bytes32 _leaf) public pure returns (bool) {\\n if (_root == bytes32(0)) {\\n return false;\\n }\\n\\n return _proof.verify(_root, _leaf);\\n }\\n\\n /// @dev creates leaf hash, that has is used in merkle tree\\n /// @param _key key under which we store the value\\n /// @param _value value itself as bytes\\n /// @return leaf hash\\n function hashLeaf(bytes memory _key, bytes memory _value) public pure returns (bytes32) {\\n return keccak256(abi.encodePacked(_key, _value));\\n }\\n\\n /// @dev verifies, if provided key-value pair was part of consensus\\n /// @param _blockId consensus ID for which we doing a check\\n /// @param _proof merkle proof for pair\\n /// @param _key pair key\\n /// @param _value pair value\\n /// @return TRUE if key-value par was part of consensus, FALSE otherwise\\n function verifyProofForBlock(\\n uint256 _blockId,\\n bytes32[] memory _proof,\\n bytes memory _key,\\n bytes memory _value\\n )\\n public\\n view\\n returns (bool)\\n {\\n return _proof.verify(roots[_blockId], keccak256(abi.encodePacked(_key, _value)));\\n }\\n\\n /// @dev this is helper method, that extracts one merkle proof from many hashed provided as bytes\\n /// @param _data many hashes as bytes\\n /// @param _offset this is starting point for extraction\\n /// @param _items how many hashes to extract\\n /// @return merkle proof (array of bytes32 hashes)\\n function bytesToBytes32Array(\\n bytes memory _data,\\n uint256 _offset,\\n uint256 _items\\n )\\n public\\n pure\\n returns (bytes32[] memory)\\n {\\n bytes32[] memory dataList = new bytes32[](_items);\\n\\n // we can unchecked because we working only with `i` and `_offset`\\n // in case of wrong `_offset` it will throw\\n unchecked {\\n for (uint256 i = 0; i < _items; i++) {\\n bytes32 temp;\\n uint256 idx = (i + 1 + _offset) * 32;\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n temp := mload(add(_data, idx))\\n }\\n\\n dataList[i] = temp;\\n }\\n }\\n\\n return (dataList);\\n }\\n\\n /// @dev batch method for data verification\\n /// @param _blockIds consensus IDs for which we doing a checks\\n /// @param _proofs merkle proofs for all pair, sequence of hashes provided as bytes\\n /// @param _proofItemsCounter array of counters, each counter tells how many hashes proof for each leaf has\\n /// @param _leaves array of merkle leaves\\n /// @return results array of verification results, TRUE if leaf is part of consensus, FALSE otherwise\\n function verifyProofs(\\n uint32[] memory _blockIds,\\n bytes memory _proofs,\\n uint256[] memory _proofItemsCounter,\\n bytes32[] memory _leaves\\n )\\n public\\n view\\n returns (bool[] memory results)\\n {\\n results = new bool[](_leaves.length);\\n uint256 offset = 0;\\n\\n for (uint256 i = 0; i < _leaves.length;) {\\n results[i] = bytesToBytes32Array(_proofs, offset, _proofItemsCounter[i]).verify(\\n roots[_blockIds[i]], _leaves[i]\\n );\\n\\n unchecked {\\n // we can uncheck because it will not overflow in a lifetime, and if someone provide invalid counter\\n // we verification will not be valid (or we throw because of invalid memory access)\\n offset += _proofItemsCounter[i];\\n // we can uncheck because `i` will not overflow in a lifetime\\n i++;\\n }\\n }\\n }\\n\\n /// @param _blockId consensus ID\\n /// @return root for provided consensus ID\\n function getBlockRoot(uint32 _blockId) external view returns (bytes32) {\\n return roots[_blockId];\\n }\\n\\n /// @param _blockId consensus ID\\n /// @return timestamp for provided consensus ID\\n function getBlockTimestamp(uint32 _blockId) external view returns (uint32) {\\n return roots[_blockId] == bytes32(0) ? 0 : _blockId;\\n }\\n\\n /// @dev batch getter for FCDs\\n /// @param _keys FCDs keys to fetch\\n /// @return values array of FCDs values\\n /// @return timestamps array of FCDs timestamps\\n function getCurrentValues(bytes32[] calldata _keys)\\n external\\n view\\n returns (uint256[] memory values, uint32[] memory timestamps)\\n {\\n timestamps = new uint32[](_keys.length);\\n values = new uint256[](_keys.length);\\n\\n for (uint i=0; i<_keys.length;) {\\n FirstClassData storage numericFCD = fcds[_keys[i]];\\n values[i] = uint256(numericFCD.value);\\n timestamps[i] = numericFCD.dataTimestamp;\\n\\n unchecked {\\n // we can uncheck because `i` will not overflow in a lifetime\\n i++;\\n }\\n }\\n }\\n\\n /// @dev getter for single FCD value\\n /// @param _key FCD key\\n /// @return value FCD value\\n /// @return timestamp FCD timestamp\\n function getCurrentValue(bytes32 _key) external view returns (uint256 value, uint256 timestamp) {\\n FirstClassData storage numericFCD = fcds[_key];\\n return (uint256(numericFCD.value), numericFCD.dataTimestamp);\\n }\\n\\n /// @dev getter for single FCD value in case its type is `int`\\n /// @param _key FCD key\\n /// @return value FCD value\\n /// @return timestamp FCD timestamp\\n function getCurrentIntValue(bytes32 _key) external view returns (int256 value, uint256 timestamp) {\\n FirstClassData storage numericFCD = fcds[_key];\\n return (numericFCD.value.toInt(), numericFCD.dataTimestamp);\\n }\\n\\n function _setPadding(uint32 _padding) internal onlyOwner {\\n if (_consensusData.padding == _padding) revert NoChangeToState();\\n\\n _consensusData.padding = _padding;\\n emit LogPadding(msg.sender, _padding);\\n }\\n\\n /// @dev we cloning last block time, because we will need reference point for next submissions\\n function _cloneLastDataFromPrevChain(address _prevChain) internal {\\n (bool success, bytes memory v) = _prevChain.staticcall(abi.encode(_VERSION_SELECTOR));\\n uint256 prevVersion = success ? abi.decode(v, (uint256)) : 1;\\n\\n if (prevVersion == 1) {\\n uint32 latestId = IBaseChainV1(address(_prevChain)).getLatestBlockId();\\n _consensusData.lastTimestamp = IBaseChainV1(address(_prevChain)).getBlockTimestamp(latestId);\\n\\n // +1 because getLatestBlockId subtracts 1\\n // +1 because it might be situation when tx is already in progress in old contract\\n // and old contract do not have deprecated flag\\n _consensusData.sequence = latestId + 2;\\n _consensusData.blocksCountOffset = latestId + 2;\\n } else { // VERSION 2\\n // with new Registry, we have register/unregister methods\\n // Chain will be deprecated, so there is no need to do \\\"+1\\\" as in old version\\n // TODO what with current Registries??\\n // we need a way to make it deprecated!\\n ConsensusData memory data = BaseChain(_prevChain).getConsensusData();\\n\\n _consensusData.sequence = data.sequence;\\n _consensusData.blocksCountOffset = data.sequence;\\n _consensusData.lastTimestamp = data.lastTimestamp;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcc7d655ad64f0a17cd71331260cf48828f0396e5e3b1428b6690c12f35a95db7\",\"license\":\"MIT\"},\"contracts/Chain.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./BaseChain.sol\\\";\\n\\ncontract Chain is BaseChain {\\n IStakingBank public immutable stakingBank;\\n\\n event LogMint(address indexed minter, uint256 blockId, uint256 staked, uint256 power);\\n event LogVoter(uint256 indexed blockId, address indexed voter, uint256 vote);\\n\\n error NotEnoughSignatures();\\n error SignaturesOutOfOrder();\\n\\n /// @param _contractRegistry Registry address\\n /// @param _padding required \\\"space\\\" between blocks in seconds\\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\\n /// @param _allowForMixedType we have two \\\"types\\\" of Chain: HomeChain and ForeignChain, when we redeploying\\n /// we don't want to mix up them, so we checking, if new Chain has the same type as current one.\\n /// However, when we will be switching from one homechain to another one, we have to allow for this mixing up.\\n /// This flag will tell contract, if this is the case.\\n constructor(\\n IRegistry _contractRegistry,\\n uint32 _padding,\\n uint16 _requiredSignatures,\\n bool _allowForMixedType\\n ) BaseChain(_contractRegistry, _padding, _requiredSignatures, _allowForMixedType) {\\n stakingBank = IStakingBank(_contractRegistry.requireAndGetAddress(\\\"StakingBank\\\"));\\n }\\n\\n /// @dev method for submitting consensus data\\n /// @param _dataTimestamp consensus timestamp, this is time for all data in merkle tree including FCDs\\n /// @param _root merkle root\\n /// @param _keys FCDs keys\\n /// @param _values FCDs values\\n /// @param _v array of `v` part of validators signatures\\n /// @param _r array of `r` part of validators signatures\\n /// @param _s array of `s` part of validators signatures\\n // solhint-disable-next-line function-max-lines, code-complexity\\n function submit(\\n uint32 _dataTimestamp,\\n bytes32 _root,\\n bytes32[] memory _keys,\\n uint256[] memory _values,\\n uint8[] memory _v,\\n bytes32[] memory _r,\\n bytes32[] memory _s\\n ) external {\\n // below two checks are only for pretty errors, so we can safe gas and allow for raw revert\\n // if (_keys.length != _values.length) revert ArraysDataDoNotMatch();\\n // if (_v.length != _r.length || _r.length != _s.length) revert ArraysDataDoNotMatch();\\n\\n _verifySubmitTimestampAndIncSequence(_dataTimestamp);\\n\\n // we can't expect minter will have exactly the same timestamp\\n // but for sure we can demand not to be off by a lot, that's why +3sec\\n // temporary remove this condition, because recently on ropsten we see cases when minter/node\\n // can be even 100sec behind\\n // require(_dataTimestamp <= block.timestamp + 3,\\n // string(abi.encodePacked(\\\"oh, so you can predict the future:\\\", _dataTimestamp - block.timestamp + 48)));\\n\\n bytes memory testimony = abi.encodePacked(_dataTimestamp, _root);\\n\\n for (uint256 i = 0; i < _keys.length;) {\\n if (uint224(_values[i]) != _values[i]) revert FCDOverflow();\\n\\n fcds[_keys[i]] = FirstClassData(uint224(_values[i]), _dataTimestamp);\\n testimony = abi.encodePacked(testimony, _keys[i], _values[i]);\\n\\n unchecked {\\n // we can't pass enough data to overflow\\n i++;\\n }\\n }\\n\\n uint256 signatures = 0;\\n uint256 power = 0;\\n //uint256 staked = stakingBank.totalSupply();\\n bytes32 affidavit = keccak256(testimony);\\n\\n address prevSigner = address(0x0);\\n\\n for (uint256 i; i < _v.length;) {\\n address signer = recoverSigner(affidavit, _v[i], _r[i], _s[i]);\\n uint256 balance = stakingBank.balanceOf(signer);\\n\\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\\n\\n prevSigner = signer;\\n\\n if (balance == 0) {\\n unchecked { i++; }\\n continue;\\n }\\n\\n signatures++;\\n emit LogVoter(uint256(_dataTimestamp), signer, balance);\\n\\n unchecked {\\n // we can't overflow because that means token overflowed\\n // and even if we do, we will get lower power\\n power += balance;\\n i++;\\n }\\n }\\n\\n if (signatures < _REQUIRED_SIGNATURES) revert NotEnoughSignatures();\\n\\n emit LogMint(msg.sender, _dataTimestamp, stakingBank.totalSupply(), power);\\n\\n // TODO remember to protect against flash loans when DPoS will be in place\\n // we turn on power once we have DPoS in action, we have PoA now\\n // require(power * 100 / staked >= 66, \\\"not enough power was gathered\\\");\\n\\n roots[_dataTimestamp] = _root;\\n _consensusData.lastTimestamp = _dataTimestamp;\\n }\\n\\n /// @inheritdoc BaseChain\\n function isForeign() external pure virtual override returns (bool) {\\n return false;\\n }\\n\\n /// @dev helper method that returns all important data about current state of contract\\n /// @return blockNumber `block.number`\\n /// @return timePadding `this.padding`\\n /// @return lastDataTimestamp timestamp for last submitted consensus\\n /// @return lastId ID of last submitted consensus\\n /// @return nextLeader leader for `block.timestamp + 1`\\n /// @return nextBlockId block ID for `block.timestamp + padding`\\n /// @return validators array of all validators addresses\\n /// @return powers array of all validators powers\\n /// @return locations array of all validators locations\\n /// @return staked total UMB staked by validators\\n /// @return minSignatures `this.requiredSignatures`\\n function getStatus() external view virtual returns(\\n uint256 blockNumber,\\n uint32 timePadding,\\n uint32 lastDataTimestamp,\\n uint32 lastId,\\n address nextLeader,\\n uint32 nextBlockId,\\n address[] memory validators,\\n uint256[] memory powers,\\n string[] memory locations,\\n uint256 staked,\\n uint16 minSignatures\\n ) {\\n ConsensusData memory data = _consensusData;\\n\\n blockNumber = block.number;\\n timePadding = data.padding;\\n lastId = data.lastTimestamp;\\n lastDataTimestamp = lastId;\\n minSignatures = _REQUIRED_SIGNATURES;\\n\\n staked = stakingBank.totalSupply();\\n uint256 numberOfValidators = stakingBank.getNumberOfValidators();\\n powers = new uint256[](numberOfValidators);\\n validators = new address[](numberOfValidators);\\n locations = new string[](numberOfValidators);\\n\\n for (uint256 i = 0; i < numberOfValidators;) {\\n validators[i] = stakingBank.addresses(i);\\n (, locations[i]) = stakingBank.validators(validators[i]);\\n powers[i] = stakingBank.balanceOf(validators[i]);\\n\\n unchecked {\\n // we will run out of gas before overflow happen\\n i++;\\n }\\n }\\n\\n unchecked {\\n // we will not overflow with timestamp in a lifetime\\n nextBlockId = lastId + data.padding + 1;\\n\\n nextLeader = numberOfValidators > 0\\n // we will not overflow with timestamp in a lifetime\\n ? validators[getLeaderIndex(numberOfValidators, block.timestamp + 1)]\\n : address(0);\\n }\\n }\\n\\n /// @return address of leader for next second\\n function getNextLeaderAddress() external view returns (address) {\\n return getLeaderAddressAtTime(block.timestamp + 1);\\n }\\n\\n /// @return address of current leader\\n function getLeaderAddress() external view returns (address) {\\n return getLeaderAddressAtTime(block.timestamp);\\n }\\n\\n /// @param _numberOfValidators total number of validators\\n /// @param _timestamp timestamp for which you want to calculate index\\n /// @return leader index, use it for StakingBank.addresses[index] to fetch leader address\\n function getLeaderIndex(uint256 _numberOfValidators, uint256 _timestamp) public view virtual returns (uint256) {\\n ConsensusData memory data = _consensusData;\\n\\n unchecked {\\n // we will not overflow on `timestamp` and `padding` in a life time\\n // timePadding + 1 => because padding is a space between blocks,\\n // so next round starts on first block after padding\\n // TODO will it work for off-chain??\\n uint256 validatorIndex = data.sequence + (_timestamp - data.lastTimestamp) / (data.padding + 1);\\n\\n return validatorIndex % _numberOfValidators;\\n }\\n }\\n\\n // @todo - properly handled non-enabled validators, newly added validators, and validators with low stake\\n /// @param _timestamp timestamp for which you want to calculate leader address\\n /// @return leader address for provider timestamp\\n function getLeaderAddressAtTime(uint256 _timestamp) public view virtual returns (address) {\\n uint256 numberOfValidators = stakingBank.getNumberOfValidators();\\n\\n if (numberOfValidators == 0) {\\n return address(0x0);\\n }\\n\\n uint256 validatorIndex = getLeaderIndex(numberOfValidators, _timestamp);\\n\\n return stakingBank.addresses(validatorIndex);\\n }\\n\\n /// @dev we had stack too deep in `submit` so this method was created as a solution\\n // we increasing `_consensusData.sequence` here so we don't have to read sequence again in other place\\n function _verifySubmitTimestampAndIncSequence(uint256 _dataTimestamp) internal {\\n ConsensusData memory data = _consensusData;\\n\\n // `data.lastTimestamp` must be setup either on deployment\\n // or via cloning from previous contract\\n if (data.lastTimestamp == 0) revert ContractNotReady();\\n\\n unchecked {\\n // we will not overflow with timestamp and padding in a life time\\n if (data.lastTimestamp + data.padding >= _dataTimestamp) revert BlockSubmittedToFastOrDataToOld();\\n }\\n\\n unchecked {\\n // we will not overflow in a life time\\n _consensusData.sequence = uint32(data.sequence + 1);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9eb872eaabac21d63c759e91507992710232a362afad6aa3221a8758d66f4e69\",\"license\":\"MIT\"},\"contracts/ForeignChain.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./Chain.sol\\\";\\n\\n/// @dev contract for foreign chains\\ncontract ForeignChain is Chain {\\n error NotSupported();\\n\\n /// @param _contractRegistry Registry address\\n /// @param _padding required \\\"space\\\" between blocks in seconds\\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\\n constructor(\\n IRegistry _contractRegistry,\\n uint32 _padding,\\n uint16 _requiredSignatures,\\n bool _allowForMixedType\\n ) Chain(_contractRegistry, _padding, _requiredSignatures, _allowForMixedType) {\\n // no additional configuration needed\\n }\\n\\n /// @inheritdoc BaseChain\\n function isForeign() external pure override returns (bool) {\\n return true;\\n }\\n\\n /// @inheritdoc Chain\\n /// @notice this method is made to be compatible with MasterChain, but it does not return full data eg validators\\n /// data will be missing.\\n /// @return blockNumber `block.number`\\n /// @return timePadding `this.padding`\\n /// @return lastDataTimestamp timestamp for last submitted consensus\\n /// @return lastId ID of last submitted consensus\\n /// @return nextLeader will be always address(0)\\n /// @return nextBlockId block ID for `block.timestamp + padding`\\n /// @return validators array will be always empty\\n /// @return powers array will be always empty\\n /// @return locations array will be always empty\\n /// @return staked total UMB staked by validators\\n /// @return minSignatures `this.requiredSignatures`\\n function getStatus() external view override returns(\\n uint256 blockNumber,\\n uint32 timePadding,\\n uint32 lastDataTimestamp,\\n uint32 lastId,\\n address nextLeader,\\n uint32 nextBlockId,\\n address[] memory validators,\\n uint256[] memory powers,\\n string[] memory locations,\\n uint256 staked,\\n uint16 minSignatures\\n ) {\\n ConsensusData memory data = _consensusData;\\n\\n blockNumber = block.number;\\n timePadding = data.padding;\\n lastId = data.lastTimestamp;\\n lastDataTimestamp = lastId;\\n minSignatures = _REQUIRED_SIGNATURES;\\n\\n staked = stakingBank.totalSupply();\\n uint256 numberOfValidators = 0;\\n powers = new uint256[](numberOfValidators);\\n validators = new address[](numberOfValidators);\\n locations = new string[](numberOfValidators);\\n nextLeader = address(0);\\n\\n unchecked {\\n // we will not overflow with timestamp in a lifetime\\n nextBlockId = lastId + data.padding + 1;\\n }\\n }\\n\\n function getLeaderIndex(uint256, uint256) public pure override returns (uint256) {\\n revert NotSupported();\\n }\\n\\n function getLeaderAddressAtTime(uint256) public pure override returns (address) {\\n revert NotSupported();\\n }\\n}\\n\",\"keccak256\":\"0x5b895277453aa3741c2659f335c2a4d587ff231615e4ee160bd2ec8e78778d49\",\"license\":\"MIT\"},\"contracts/Registry.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\n// Inheritance\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport \\\"./extensions/Registrable.sol\\\";\\nimport \\\"./interfaces/IRegistry.sol\\\";\\n\\n/// @dev contracts registry\\n/// protocol uses this registry to fetch current contract addresses\\ncontract Registry is IRegistry, Ownable {\\n /// name => contract address\\n mapping(bytes32 => address) public registry;\\n\\n\\n error NameNotRegistered();\\n error ArraysDataDoNotMatch();\\n\\n /// @inheritdoc IRegistry\\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external onlyOwner {\\n if (_names.length != _destinations.length) revert ArraysDataDoNotMatch();\\n\\n for (uint i = 0; i < _names.length;) {\\n registry[_names[i]] = _destinations[i];\\n emit LogRegistered(_destinations[i], _names[i]);\\n\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @inheritdoc IRegistry\\n function importContracts(address[] calldata _destinations) external onlyOwner {\\n for (uint i = 0; i < _destinations.length;) {\\n bytes32 name = Registrable(_destinations[i]).getName();\\n registry[name] = _destinations[i];\\n emit LogRegistered(_destinations[i], name);\\n\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @inheritdoc IRegistry\\n function atomicUpdate(address _newContract) external onlyOwner {\\n Registrable(_newContract).register();\\n\\n bytes32 name = Registrable(_newContract).getName();\\n address oldContract = registry[name];\\n registry[name] = _newContract;\\n\\n Registrable(oldContract).unregister();\\n\\n emit LogRegistered(_newContract, name);\\n }\\n\\n /// @inheritdoc IRegistry\\n function requireAndGetAddress(bytes32 name) external view returns (address) {\\n address _foundAddress = registry[name];\\n if (_foundAddress == address(0)) revert NameNotRegistered();\\n\\n return _foundAddress;\\n }\\n\\n /// @inheritdoc IRegistry\\n function getAddress(bytes32 _bytes) external view returns (address) {\\n return registry[_bytes];\\n }\\n\\n /// @inheritdoc IRegistry\\n function getAddressByString(string memory _name) public view returns (address) {\\n return registry[stringToBytes32(_name)];\\n }\\n\\n /// @inheritdoc IRegistry\\n function stringToBytes32(string memory _string) public pure returns (bytes32 result) {\\n bytes memory tempEmptyStringTest = bytes(_string);\\n\\n if (tempEmptyStringTest.length == 0) {\\n return 0x0;\\n }\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n result := mload(add(_string, 32))\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcf8ac18bf5766420afcc70f34339192fa67169106ccdb51573267a1ffd95fb81\",\"license\":\"MIT\"},\"contracts/extensions/Registrable.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"../interfaces/IRegistry.sol\\\";\\nimport \\\"../interfaces/IStakingBank.sol\\\";\\n\\n/// @dev Any contract that we want to register in ContractRegistry, must inherit from Registrable\\nabstract contract Registrable {\\n IRegistry public immutable contractRegistry;\\n\\n modifier onlyFromContract(address _msgSender, bytes32 _contractName) {\\n require(\\n contractRegistry.getAddress(_contractName) == _msgSender,\\n string(abi.encodePacked(\\\"caller is not \\\", _contractName))\\n );\\n _;\\n }\\n\\n modifier withRegistrySetUp() {\\n require(address(contractRegistry) != address(0x0), \\\"_registry is empty\\\");\\n _;\\n }\\n\\n constructor(IRegistry _contractRegistry) {\\n require(address(_contractRegistry) != address(0x0), \\\"_registry is empty\\\");\\n contractRegistry = _contractRegistry;\\n }\\n\\n /// @dev this method will be called as a first method in registration process when old contract will be replaced\\n /// when called, old contract address is still in registry\\n function register() virtual external;\\n\\n /// @dev this method will be called as a last method in registration process when old contract will be replaced\\n /// when called, new contract address is already in registry\\n function unregister() virtual external;\\n\\n /// @return contract name as bytes32\\n function getName() virtual external pure returns (bytes32);\\n\\n /// @dev helper method for fetching StakingBank address\\n function stakingBankContract() public view returns (IStakingBank) {\\n return IStakingBank(contractRegistry.requireAndGetAddress(\\\"StakingBank\\\"));\\n }\\n\\n /// @dev helper method for fetching UMB address\\n function tokenContract() public view withRegistrySetUp returns (ERC20) {\\n return ERC20(contractRegistry.requireAndGetAddress(\\\"UMB\\\"));\\n }\\n}\\n\",\"keccak256\":\"0x58413fc819ff8f78ba80a9339bf6b4bb818932ddef0ce58dd4813acba01bda8c\",\"license\":\"MIT\"},\"contracts/interfaces/IBaseChainV1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IBaseChainV1 {\\n /// @dev number of blocks (consensus rounds) saved in this contract\\n function blocksCount() external returns (uint32);\\n\\n /// @dev number of all blocks that were generated before switching to this contract\\n /// please note, that there might be a gap of one block when we switching from old to new contract\\n /// see constructor for details\\n function blocksCountOffset() external returns (uint32);\\n\\n function getLatestBlockId() external view returns (uint32);\\n\\n function getBlockTimestamp(uint32 _blockId) external view returns (uint32);\\n\\n function getStatus() external view returns (\\n uint256 blockNumber,\\n uint16 timePadding,\\n uint32 lastDataTimestamp,\\n uint32 lastId,\\n uint32 nextBlockId\\n );\\n}\\n\",\"keccak256\":\"0x4196faa25b921cae447328983f172ee4289591b4136fdde54ad05552c559d371\",\"license\":\"MIT\"},\"contracts/interfaces/IRegistry.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\n\\ninterface IRegistry {\\n event LogRegistered(address indexed destination, bytes32 name);\\n\\n /// @dev imports new contract addresses and override old addresses, if they exist under provided name\\n /// This method can be used for contracts that for some reason do not have `getName` method\\n /// @param _names array of contract names that we want to register\\n /// @param _destinations array of contract addresses\\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external;\\n\\n /// @dev imports new contracts and override old addresses, if they exist.\\n /// Names of contracts are fetched directly from each contract by calling `getName`\\n /// @param _destinations array of contract addresses\\n function importContracts(address[] calldata _destinations) external;\\n\\n /// @dev this method ensure, that old and new contract is aware of it state in registry\\n /// Note: BSC registry does not have this method. This method was introduced in later stage.\\n /// @param _newContract address of contract that will replace old one\\n function atomicUpdate(address _newContract) external;\\n\\n /// @dev similar to `getAddress` but throws when contract name not exists\\n /// @param name contract name\\n /// @return contract address registered under provided name or throws, if does not exists\\n function requireAndGetAddress(bytes32 name) external view returns (address);\\n\\n /// @param name contract name in a form of bytes32\\n /// @return contract address registered under provided name\\n function getAddress(bytes32 name) external view returns (address);\\n\\n /// @param _name contract name\\n /// @return contract address assigned to the name or address(0) if not exists\\n function getAddressByString(string memory _name) external view returns (address);\\n\\n /// @dev helper method that converts string to bytes32,\\n /// you can use to to generate contract name\\n function stringToBytes32(string memory _string) external pure returns (bytes32 result);\\n}\\n\",\"keccak256\":\"0xa0099ecf4182138fda7a0733407784461410c245de67c1e7ba7cd7c9595e054f\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBank.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IStakingBank is IERC20 {\\n /// @param id address of validator wallet\\n /// @param location URL of the validator API\\n struct Validator {\\n address id;\\n string location;\\n }\\n\\n event LogValidatorRegistered(address indexed id);\\n event LogValidatorUpdated(address indexed id);\\n event LogValidatorRemoved(address indexed id);\\n event LogMinAmountForStake(uint256 minAmountForStake);\\n\\n /// @dev setter for `minAmountForStake`\\n function setMinAmountForStake(uint256 _minAmountForStake) external;\\n\\n /// @dev allows to stake `token` by validators\\n /// Validator needs to approve StakingBank beforehand\\n /// @param _value amount of tokens to stake\\n function stake(uint256 _value) external;\\n\\n /// @dev notification about approval from `_from` address on UMB token\\n /// Staking bank will stake max approved amount from `_from` address\\n /// @param _from address which approved token spend for IStakingBank\\n function receiveApproval(address _from) external returns (bool success);\\n\\n /// @dev withdraws stake tokens\\n /// it throws, when balance will be less than required minimum for stake\\n /// to withdraw all use `exit`\\n function withdraw(uint256 _value) external returns (bool success);\\n\\n /// @dev unstake and withdraw all tokens\\n function exit() external returns (bool success);\\n\\n /// @dev creates (register) new validator\\n /// @param _id validator address\\n /// @param _location location URL of the validator API\\n function create(address _id, string calldata _location) external;\\n\\n /// @dev removes validator\\n /// @param _id validator wallet\\n function remove(address _id) external;\\n\\n /// @dev updates validator location\\n /// @param _id validator wallet\\n /// @param _location new validator URL\\n function update(address _id, string calldata _location) external;\\n\\n /// @return total number of registered validators (with and without balance)\\n function getNumberOfValidators() external view returns (uint256);\\n\\n /// @dev gets validator address for provided index\\n /// @param _ix index in array of list of all validators wallets\\n function addresses(uint256 _ix) external view returns (address);\\n\\n /// @param _id address of validator\\n /// @return id address of validator\\n /// @return location URL of validator\\n function validators(address _id) external view returns (address id, string memory location);\\n}\\n\",\"keccak256\":\"0x2c518aeab8b0b3a364fafaec559d3ff0dc6a119f8d203fa31ef7ad667ca0f7b9\",\"license\":\"MIT\"}},\"version\":1}", "bytecode": "0x6101006040523480156200001257600080fd5b50604051620057fa380380620057fa83398181016040528101906200003891906200067f565b838383838383838383600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603620000b3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620000aa9062000752565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250505062000108620000fc620002ee60201b60201c565b620002f660201b60201c565b80151560a0811515815250508161ffff1660c08161ffff16815250506200013583620003ba60201b60201c565b60008473ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b815260040162000170906200079a565b602060405180830381865afa1580156200018e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001b49190620007e6565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036200022b5760018442620001fb919062000847565b62000207919062000847565b600160000160086101000a81548163ffffffff021916908363ffffffff1602179055505b50505050508373ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b81526004016200026990620008a8565b602060405180830381865afa15801562000287573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002ad9190620007e6565b73ffffffffffffffffffffffffffffffffffffffff1660e08173ffffffffffffffffffffffffffffffffffffffff1681525050505050505050505062000963565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b620003ca620002ee60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16620003f06200051b60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff161462000449576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620004409062000913565b60405180910390fd5b8063ffffffff166001600001600c9054906101000a900463ffffffff1663ffffffff1603620004a4576040517f96f56f6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600001600c6101000a81548163ffffffff021916908363ffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167f02ff77a0f68d11f7efb906f331b2dda82916de8ba9c37dda2a95817936a530ec8260405162000510919062000946565b60405180910390a250565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620005768262000549565b9050919050565b60006200058a8262000569565b9050919050565b6200059c816200057d565b8114620005a857600080fd5b50565b600081519050620005bc8162000591565b92915050565b600063ffffffff82169050919050565b620005dd81620005c2565b8114620005e957600080fd5b50565b600081519050620005fd81620005d2565b92915050565b600061ffff82169050919050565b6200061c8162000603565b81146200062857600080fd5b50565b6000815190506200063c8162000611565b92915050565b60008115159050919050565b620006598162000642565b81146200066557600080fd5b50565b60008151905062000679816200064e565b92915050565b600080600080608085870312156200069c576200069b62000544565b5b6000620006ac87828801620005ab565b9450506020620006bf87828801620005ec565b9350506040620006d2878288016200062b565b9250506060620006e58782880162000668565b91505092959194509250565b600082825260208201905092915050565b7f5f726567697374727920697320656d7074790000000000000000000000000000600082015250565b60006200073a601283620006f1565b9150620007478262000702565b602082019050919050565b600060208201905081810360008301526200076d816200072b565b9050919050565b7f436861696e000000000000000000000000000000000000000000000000000000815250565b6000602082019050620007b06000830162000774565b919050565b620007c08162000569565b8114620007cc57600080fd5b50565b600081519050620007e081620007b5565b92915050565b600060208284031215620007ff57620007fe62000544565b5b60006200080f84828501620007cf565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006200085482620005c2565b91506200086183620005c2565b92508282101562000877576200087662000818565b5b828203905092915050565b7f5374616b696e6742616e6b000000000000000000000000000000000000000000815250565b6000602082019050620008be6000830162000882565b919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000620008fb602083620006f1565b91506200090882620008c3565b602082019050919050565b600060208201905081810360008301526200092e81620008ec565b9050919050565b6200094081620005c2565b82525050565b60006020820190506200095d600083018462000935565b92915050565b60805160a05160c05160e051614e02620009f860003960008181610eac015281816112260152818161145101526116880152600081816113ba015281816116650152611bd30152600061230f01526000818161082701528181610a1d01528181610ae501528181611839015281816118b00152818161194f01528181611d0b0152818161213101526122100152614e026000f3fe608060405234801561001057600080fd5b50600436106101f95760003560e01c80630f2acc3e146101fe5780630fcc0c281461022e57806317d7de7c14610238578063199dadc5146102565780631aa3a00814610286578063243b68f91461029057806324c89a49146102c057806326f3ab8b146102de57806334ba34811461030f5780633bb8819d1461032d57806340a9e5e31461035e578063485e055d1461037a5780634bc935d7146103965780634e69d560146103c657806355a373d6146103ee578063637180a81461040c5780636d046c3e1461042a578063715018a6146104485780637353cbcb1461045257806377839fe614610470578063805d34321461048e5780638d068043146104be5780638da5cb5b146104dc5780639f6119d7146104fa578063a0bc937414610518578063abf410e514610536578063adf1639d14610554578063bef9f8a114610585578063bf66e3ba146105b5578063c2a4250b146105e5578063c2b40ae414610603578063c3369db814610633578063ca4d29d214610663578063cbb1b2c714610693578063d3d3ea08146106c4578063d45167d0146106e2578063e76c0b5714610712578063e79a198f14610730578063ed9975c31461073a578063ef19f3e714610758578063f25b3f9914610788578063f2fde38b146107b8578063ffa1ad74146107d4575b600080fd5b61021860048036038101906102139190613017565b6107f2565b60405161022591906130a8565b60405180910390f35b610236610825565b005b610240610997565b60405161024d91906130a8565b60405180910390f35b610270600480360381019061026b91906131ed565b6109bf565b60405161027d91906132c3565b60405180910390f35b61028e610a1b565b005b6102aa60048036038101906102a591906132de565b610c29565b6040516102b7919061340b565b60405180910390f35b6102c8610cd2565b6040516102d591906134b5565b60405180910390f35b6102f860048036038101906102f39190613532565b610d0b565b60405161030692919061370b565b60405180910390f35b610317610eaa565b60405161032491906137c1565b60405180910390f35b610347600480360381019061034291906137dc565b610ece565b604051610355929190613831565b60405180910390f35b61037860048036038101906103739190613894565b610f63565b005b610394600480360381019061038f9190613aac565b610f73565b005b6103b060048036038101906103ab9190613bda565b611546565b6040516103bd91906132c3565b60405180910390f35b6103ce61157a565b6040516103e59b9a99989796959493929190613e5d565b60405180910390f35b6103f661181e565b6040516104039190613f3e565b60405180910390f35b61041461194b565b60405161042191906137c1565b60405180910390f35b6104326119ea565b60405161043f91906132c3565b60405180910390f35b6104506119f3565b005b61045a611a7b565b6040516104679190613f59565b60405180910390f35b610478611abe565b6040516104859190613f74565b60405180910390f35b6104a860048036038101906104a39190613f8f565b611adb565b6040516104b59190613f74565b60405180910390f35b6104c6611bcf565b6040516104d39190613fbc565b60405180910390f35b6104e4611bf7565b6040516104f19190613fd7565b60405180910390f35b610502611c20565b60405161050f9190613fd7565b60405180910390f35b610520611c3c565b60405161052d9190614069565b60405180910390f35b61053e611d09565b60405161054b91906140a5565b60405180910390f35b61056e600480360381019061056991906137dc565b611d2d565b60405161057c9291906140c0565b60405180910390f35b61059f600480360381019061059a91906140e9565b611dba565b6040516105ac91906130a8565b60405180910390f35b6105cf60048036038101906105ca91906141d9565b611ddd565b6040516105dc919061435f565b60405180910390f35b6105ed611f19565b6040516105fa9190613f59565b60405180910390f35b61061d60048036038101906106189190613f8f565b611f3c565b60405161062a91906130a8565b60405180910390f35b61064d600480360381019061064891906140e9565b611f54565b60405161065a9190613f74565b60405180910390f35b61067d60048036038101906106789190614381565b611f89565b60405161068a9190613f59565b60405180910390f35b6106ad60048036038101906106a891906137dc565b611fbd565b6040516106bb9291906143f8565b60405180910390f35b6106cc612019565b6040516106d99190613f74565b60405180910390f35b6106fc60048036038101906106f79190614421565b612036565b6040516107099190613fd7565b60405180910390f35b61071a6120f3565b6040516107279190613f74565b60405180910390f35b61073861212f565b005b6107426124b0565b60405161074f9190613fd7565b60405180910390f35b610772600480360381019061076d9190613f8f565b6124c0565b60405161077f9190613fd7565b60405180910390f35b6107a2600480360381019061079d9190613f8f565b6124f4565b6040516107af91906144b7565b60405180910390f35b6107d260048036038101906107cd91906144fe565b612531565b005b6107dc612628565b6040516107e99190613f59565b60405180910390f35b60008282604051602001610807929190614567565b60405160208183030381529060405280519060200120905092915050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156108b45750610884611bf7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156108eb576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160000160109054906101000a900460ff1615610935576040517f764c143b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018060000160106101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167fd4ae81319f0b4df100dcda9ce971671b97278c7a5ce6b37a8331a44700679fd460405160405180910390a2565b60007f436861696e000000000000000000000000000000000000000000000000000000905090565b6000610a11600260008781526020019081526020016000205484846040516020016109eb929190614567565b604051602081830303815290604052805190602001208661262d9092919063ffffffff16565b9050949350505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015610aaa5750610a7a611bf7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15610ae1576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b8152600401610b3a906145b1565b602060405180830381865afa158015610b57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7b91906145df565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610be2576040517f3a81d6fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610c1c5750610c27565b610c2581612644565b505b565b606060008267ffffffffffffffff811115610c4757610c46612eec565b5b604051908082528060200260200182016040528015610c755781602001602082028036833780820191505090505b50905060005b83811015610cc657600080602087600185010102905080880151915081848481518110610cab57610caa61460c565b5b60200260200101818152505050508080600101915050610c7b565b50809150509392505050565b6040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525081565b6060808383905067ffffffffffffffff811115610d2b57610d2a612eec565b5b604051908082528060200260200182016040528015610d595781602001602082028036833780820191505090505b5090508383905067ffffffffffffffff811115610d7957610d78612eec565b5b604051908082528060200260200182016040528015610da75781602001602082028036833780820191505090505b50915060005b84849050811015610ea257600060036000878785818110610dd157610dd061460c565b5b90506020020135815260200190815260200160002090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16848381518110610e4657610e4561460c565b5b60200260200101818152505080600001601c9054906101000a900463ffffffff16838381518110610e7a57610e7961460c565b5b602002602001019063ffffffff16908163ffffffff1681525050818060010192505050610dad565b509250929050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806000600360008581526020019081526020016000209050610f3b8160000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16612986565b81600001601c9054906101000a900463ffffffff168063ffffffff1690509250925050915091565b610f708161ffff16612a2e565b50565b610f828763ffffffff16612b79565b60008787604051602001610f97929190614692565b604051602081830303815290604052905060005b86518110156111a757858181518110610fc757610fc661460c565b5b6020026020010151868281518110610fe257610fe161460c565b5b60200260200101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff161461103f576040517f6980091000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604051806040016040528087838151811061105d5761105c61460c565b5b60200260200101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681526020018a63ffffffff16815250600360008984815181106110a9576110a861460c565b5b6020026020010151815260200190815260200160002060008201518160000160006101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff160217905550602082015181600001601c6101000a81548163ffffffff021916908363ffffffff160217905550905050818782815181106111545761115361460c565b5b602002602001015187838151811061116f5761116e61460c565b5b6020026020010151604051602001611189939291906146df565b60405160208183030381529060405291508080600101915050610fab565b506000806000838051906020012090506000805b88518110156113b7576000611220848b84815181106111dd576111dc61460c565b5b60200260200101518b85815181106111f8576111f761460c565b5b60200260200101518b86815181106112135761121261460c565b5b6020026020010151612036565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231836040518263ffffffff1660e01b815260040161127d9190613fd7565b602060405180830381865afa15801561129a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112be919061472d565b90508173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1610611325576040517f9079f69b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8193506000810361133f57828060010193505050506113b2565b868061134a90614789565b9750508173ffffffffffffffffffffffffffffffffffffffff168f63ffffffff167fbac7552ab5da8d0588709ddb75aceec28520646f54bca1cc5e6e104db61935ec8360405161139a9190613f59565b60405180910390a38086019550828060010193505050505b6111bb565b507f000000000000000000000000000000000000000000000000000000000000000061ffff16841015611416576040517fe246dc6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167f5f11830295067c4bcc7d02d4e3b048cd7427be50a3aeb6afc9d3d559ee64bcfa8d7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114de919061472d565b866040516114ee93929190614802565b60405180910390a28a600260008e63ffffffff168152602001908152602001600020819055508b600160000160086101000a81548163ffffffff021916908363ffffffff160217905550505050505050505050505050565b60008060001b830361155b5760009050611573565b61157083838661262d9092919063ffffffff16565b90505b9392505050565b6000806000806000806060806060600080600060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff1615151515815250509050439b5080606001519a50806040015198508899507f000000000000000000000000000000000000000000000000000000000000000091507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611715919061472d565b925060008067ffffffffffffffff81111561173357611732612eec565b5b6040519080825280602002602001820160405280156117615781602001602082028036833780820191505090505b5095508067ffffffffffffffff81111561177e5761177d612eec565b5b6040519080825280602002602001820160405280156117ac5781602001602082028036833780820191505090505b5096508067ffffffffffffffff8111156117c9576117c8612eec565b5b6040519080825280602002602001820160405280156117fc57816020015b60608152602001906001900390816117e75790505b50945060009850600182606001518b010197505050909192939495969798999a565b60008073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16036118ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118a590614896565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b8152600401611905906148dc565b602060405180830381865afa158015611922573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194691906145df565b905090565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b81526004016119a49061491b565b602060405180830381865afa1580156119c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e591906145df565b905090565b60006001905090565b6119fb612cf9565b73ffffffffffffffffffffffffffffffffffffffff16611a19611bf7565b73ffffffffffffffffffffffffffffffffffffffff1614611a6f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a6690614980565b60405180910390fd5b611a796000612d01565b565b6000600160000160009054906101000a900463ffffffff16600160000160049054906101000a900463ffffffff16611ab391906149a0565b63ffffffff16905090565b6000600160000160009054906101000a900463ffffffff16905090565b60008060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff161515151581525050905082816060015182604001510163ffffffff161015611bc15782915050611bca565b80604001519150505b919050565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000611c37600142611c3291906149d4565b6124c0565b905090565b611c44612e51565b60016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff161515151581525050905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060006003600085815260200190815260200160002090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681600001601c9054906101000a900463ffffffff168063ffffffff1690509250925050915091565b6000600260008363ffffffff168152602001908152602001600020549050919050565b6060815167ffffffffffffffff811115611dfa57611df9612eec565b5b604051908082528060200260200182016040528015611e285781602001602082028036833780820191505090505b5090506000805b8351811015611f0f57611ebe60026000898481518110611e5257611e5161460c565b5b602002602001015163ffffffff16815260200190815260200160002054858381518110611e8257611e8161460c565b5b6020026020010151611eaf89868a8781518110611ea257611ea161460c565b5b6020026020010151610c29565b61262d9092919063ffffffff16565b838281518110611ed157611ed061460c565b5b602002602001019015159081151581525050848181518110611ef657611ef561460c565b5b6020026020010151820191508080600101915050611e2f565b5050949350505050565b6000600160000160089054906101000a900463ffffffff1663ffffffff16905090565b60026020528060005260406000206000915090505481565b60008060001b600260008463ffffffff1681526020019081526020016000205414611f7f5781611f82565b60005b9050919050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60036020528060005260406000206000915090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169080600001601c9054906101000a900463ffffffff16905082565b6000600160000160089054906101000a900463ffffffff16905090565b6000806040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525086604051602001612081929190614a2a565b604051602081830303815290604052805190602001209050600181868686604051600081526020016040526040516120bc9493929190614a61565b6020604051602081039080840390855afa1580156120de573d6000803e3d6000fd5b50505060206040510351915050949350505050565b600080600160000160089054906101000a900463ffffffff1663ffffffff1603612120576000905061212c565b61212942611adb565b90505b90565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156121be575061218e611bf7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156121f5576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160000160109054906101000a900460ff166124ae5760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b8152600401612265906145b1565b602060405180830381865afa158015612282573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122a691906145df565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361230d576040517ff8e0084400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061244c573073ffffffffffffffffffffffffffffffffffffffff16636d046c3e6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561237d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123a19190614ad2565b15158173ffffffffffffffffffffffffffffffffffffffff16636d046c3e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124129190614ad2565b15151461244b576040517f07b72f5e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b60018060000160106101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167fd4ae81319f0b4df100dcda9ce971671b97278c7a5ce6b37a8331a44700679fd460405160405180910390a2505b565b60006124bb426124c0565b905090565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6124fc612e9a565b6040518060400160405280600260008581526020019081526020016000205481526020018363ffffffff168152509050919050565b612539612cf9565b73ffffffffffffffffffffffffffffffffffffffff16612557611bf7565b73ffffffffffffffffffffffffffffffffffffffff16146125ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125a490614980565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361261c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161261390614b71565b60405180910390fd5b61262581612d01565b50565b600281565b60008261263a8584612dc5565b1490509392505050565b6000808273ffffffffffffffffffffffffffffffffffffffff167fffa1ad74ba96b4c159a84d090433911c3991c54f629eb60d0c84aed3be5f067c60405160200161268f9190614bcc565b6040516020818303038152906040526040516126ab9190614be7565b600060405180830381855afa9150503d80600081146126e6576040519150601f19603f3d011682016040523d82523d6000602084013e6126eb565b606091505b50915091506000826126fe576001612713565b81806020019051810190612712919061472d565b5b9050600181036128935760008473ffffffffffffffffffffffffffffffffffffffff1663d3d3ea086040518163ffffffff1660e01b8152600401602060405180830381865afa15801561276a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061278e9190614c13565b90508473ffffffffffffffffffffffffffffffffffffffff1663c3369db8826040518263ffffffff1660e01b81526004016127c99190613f74565b602060405180830381865afa1580156127e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061280a9190614c13565b600160000160086101000a81548163ffffffff021916908363ffffffff16021790555060028161283a9190614c40565b600160000160046101000a81548163ffffffff021916908363ffffffff16021790555060028161286a9190614c40565b600160000160006101000a81548163ffffffff021916908363ffffffff16021790555050612980565b60008473ffffffffffffffffffffffffffffffffffffffff1663a0bc93746040518163ffffffff1660e01b815260040160a060405180830381865afa1580156128e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129049190614d0b565b90508060200151600160000160046101000a81548163ffffffff021916908363ffffffff1602179055508060200151600160000160006101000a81548163ffffffff021916908363ffffffff1602179055508060400151600160000160086101000a81548163ffffffff021916908363ffffffff160217905550505b50505050565b60008060007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff905060026001826129b99190614d38565b6129c39190614d9b565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1611612a185760008401915081601b0b92505050612a29565b600181850303915081601b0b925050505b919050565b612a36612cf9565b73ffffffffffffffffffffffffffffffffffffffff16612a54611bf7565b73ffffffffffffffffffffffffffffffffffffffff1614612aaa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612aa190614980565b60405180910390fd5b8063ffffffff166001600001600c9054906101000a900463ffffffff1663ffffffff1603612b04576040517f96f56f6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600001600c6101000a81548163ffffffff021916908363ffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167f02ff77a0f68d11f7efb906f331b2dda82916de8ba9c37dda2a95817936a530ec82604051612b6e9190613f74565b60405180910390a250565b600060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff16151515158152505090506000816040015163ffffffff1603612c81576040517f96a96e1700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81816060015182604001510163ffffffff1610612cca576040517ff886149e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001816020015101600160000160046101000a81548163ffffffff021916908363ffffffff1602179055505050565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60008082905060005b8451811015612e2f576000858281518110612dec57612deb61460c565b5b60200260200101519050808311612e0e57612e078382612e3a565b9250612e1b565b612e188184612e3a565b92505b508080612e2790614789565b915050612dce565b508091505092915050565b600082600052816020526040600020905092915050565b6040518060a00160405280600063ffffffff168152602001600063ffffffff168152602001600063ffffffff168152602001600063ffffffff1681526020016000151581525090565b604051806040016040528060008019168152602001600063ffffffff1681525090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612f2482612edb565b810181811067ffffffffffffffff82111715612f4357612f42612eec565b5b80604052505050565b6000612f56612ebd565b9050612f628282612f1b565b919050565b600067ffffffffffffffff821115612f8257612f81612eec565b5b612f8b82612edb565b9050602081019050919050565b82818337600083830152505050565b6000612fba612fb584612f67565b612f4c565b905082815260208101848484011115612fd657612fd5612ed6565b5b612fe1848285612f98565b509392505050565b600082601f830112612ffe57612ffd612ed1565b5b813561300e848260208601612fa7565b91505092915050565b6000806040838503121561302e5761302d612ec7565b5b600083013567ffffffffffffffff81111561304c5761304b612ecc565b5b61305885828601612fe9565b925050602083013567ffffffffffffffff81111561307957613078612ecc565b5b61308585828601612fe9565b9150509250929050565b6000819050919050565b6130a28161308f565b82525050565b60006020820190506130bd6000830184613099565b92915050565b6000819050919050565b6130d6816130c3565b81146130e157600080fd5b50565b6000813590506130f3816130cd565b92915050565b600067ffffffffffffffff82111561311457613113612eec565b5b602082029050602081019050919050565b600080fd5b6131338161308f565b811461313e57600080fd5b50565b6000813590506131508161312a565b92915050565b6000613169613164846130f9565b612f4c565b9050808382526020820190506020840283018581111561318c5761318b613125565b5b835b818110156131b557806131a18882613141565b84526020840193505060208101905061318e565b5050509392505050565b600082601f8301126131d4576131d3612ed1565b5b81356131e4848260208601613156565b91505092915050565b6000806000806080858703121561320757613206612ec7565b5b6000613215878288016130e4565b945050602085013567ffffffffffffffff81111561323657613235612ecc565b5b613242878288016131bf565b935050604085013567ffffffffffffffff81111561326357613262612ecc565b5b61326f87828801612fe9565b925050606085013567ffffffffffffffff8111156132905761328f612ecc565b5b61329c87828801612fe9565b91505092959194509250565b60008115159050919050565b6132bd816132a8565b82525050565b60006020820190506132d860008301846132b4565b92915050565b6000806000606084860312156132f7576132f6612ec7565b5b600084013567ffffffffffffffff81111561331557613314612ecc565b5b61332186828701612fe9565b9350506020613332868287016130e4565b9250506040613343868287016130e4565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6133828161308f565b82525050565b60006133948383613379565b60208301905092915050565b6000602082019050919050565b60006133b88261334d565b6133c28185613358565b93506133cd83613369565b8060005b838110156133fe5781516133e58882613388565b97506133f0836133a0565b9250506001810190506133d1565b5085935050505092915050565b6000602082019050818103600083015261342581846133ad565b905092915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561346757808201518184015260208101905061344c565b83811115613476576000848401525b50505050565b60006134878261342d565b6134918185613438565b93506134a1818560208601613449565b6134aa81612edb565b840191505092915050565b600060208201905081810360008301526134cf818461347c565b905092915050565b600080fd5b60008083601f8401126134f2576134f1612ed1565b5b8235905067ffffffffffffffff81111561350f5761350e6134d7565b5b60208301915083602082028301111561352b5761352a613125565b5b9250929050565b6000806020838503121561354957613548612ec7565b5b600083013567ffffffffffffffff81111561356757613566612ecc565b5b613573858286016134dc565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6135b4816130c3565b82525050565b60006135c683836135ab565b60208301905092915050565b6000602082019050919050565b60006135ea8261357f565b6135f4818561358a565b93506135ff8361359b565b8060005b8381101561363057815161361788826135ba565b9750613622836135d2565b925050600181019050613603565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600063ffffffff82169050919050565b61368281613669565b82525050565b60006136948383613679565b60208301905092915050565b6000602082019050919050565b60006136b88261363d565b6136c28185613648565b93506136cd83613659565b8060005b838110156136fe5781516136e58882613688565b97506136f0836136a0565b9250506001810190506136d1565b5085935050505092915050565b6000604082019050818103600083015261372581856135df565b9050818103602083015261373981846136ad565b90509392505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061378761378261377d84613742565b613762565b613742565b9050919050565b60006137998261376c565b9050919050565b60006137ab8261378e565b9050919050565b6137bb816137a0565b82525050565b60006020820190506137d660008301846137b2565b92915050565b6000602082840312156137f2576137f1612ec7565b5b600061380084828501613141565b91505092915050565b6000819050919050565b61381c81613809565b82525050565b61382b816130c3565b82525050565b60006040820190506138466000830185613813565b6138536020830184613822565b9392505050565b600061ffff82169050919050565b6138718161385a565b811461387c57600080fd5b50565b60008135905061388e81613868565b92915050565b6000602082840312156138aa576138a9612ec7565b5b60006138b88482850161387f565b91505092915050565b6138ca81613669565b81146138d557600080fd5b50565b6000813590506138e7816138c1565b92915050565b600067ffffffffffffffff82111561390857613907612eec565b5b602082029050602081019050919050565b600061392c613927846138ed565b612f4c565b9050808382526020820190506020840283018581111561394f5761394e613125565b5b835b81811015613978578061396488826130e4565b845260208401935050602081019050613951565b5050509392505050565b600082601f83011261399757613996612ed1565b5b81356139a7848260208601613919565b91505092915050565b600067ffffffffffffffff8211156139cb576139ca612eec565b5b602082029050602081019050919050565b600060ff82169050919050565b6139f2816139dc565b81146139fd57600080fd5b50565b600081359050613a0f816139e9565b92915050565b6000613a28613a23846139b0565b612f4c565b90508083825260208201905060208402830185811115613a4b57613a4a613125565b5b835b81811015613a745780613a608882613a00565b845260208401935050602081019050613a4d565b5050509392505050565b600082601f830112613a9357613a92612ed1565b5b8135613aa3848260208601613a15565b91505092915050565b600080600080600080600060e0888a031215613acb57613aca612ec7565b5b6000613ad98a828b016138d8565b9750506020613aea8a828b01613141565b965050604088013567ffffffffffffffff811115613b0b57613b0a612ecc565b5b613b178a828b016131bf565b955050606088013567ffffffffffffffff811115613b3857613b37612ecc565b5b613b448a828b01613982565b945050608088013567ffffffffffffffff811115613b6557613b64612ecc565b5b613b718a828b01613a7e565b93505060a088013567ffffffffffffffff811115613b9257613b91612ecc565b5b613b9e8a828b016131bf565b92505060c088013567ffffffffffffffff811115613bbf57613bbe612ecc565b5b613bcb8a828b016131bf565b91505092959891949750929550565b600080600060608486031215613bf357613bf2612ec7565b5b600084013567ffffffffffffffff811115613c1157613c10612ecc565b5b613c1d868287016131bf565b9350506020613c2e86828701613141565b9250506040613c3f86828701613141565b9150509250925092565b613c5281613669565b82525050565b6000613c6382613742565b9050919050565b613c7381613c58565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b613cae81613c58565b82525050565b6000613cc08383613ca5565b60208301905092915050565b6000602082019050919050565b6000613ce482613c79565b613cee8185613c84565b9350613cf983613c95565b8060005b83811015613d2a578151613d118882613cb4565b9750613d1c83613ccc565b925050600181019050613cfd565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b6000613d8a82613d63565b613d948185613d6e565b9350613da4818560208601613449565b613dad81612edb565b840191505092915050565b6000613dc48383613d7f565b905092915050565b6000602082019050919050565b6000613de482613d37565b613dee8185613d42565b935083602082028501613e0085613d53565b8060005b85811015613e3c5784840389528151613e1d8582613db8565b9450613e2883613dcc565b925060208a01995050600181019050613e04565b50829750879550505050505092915050565b613e578161385a565b82525050565b600061016082019050613e73600083018e613822565b613e80602083018d613c49565b613e8d604083018c613c49565b613e9a606083018b613c49565b613ea7608083018a613c6a565b613eb460a0830189613c49565b81810360c0830152613ec68188613cd9565b905081810360e0830152613eda81876135df565b9050818103610100830152613eef8186613dd9565b9050613eff610120830185613822565b613f0d610140830184613e4e565b9c9b505050505050505050505050565b6000613f288261378e565b9050919050565b613f3881613f1d565b82525050565b6000602082019050613f536000830184613f2f565b92915050565b6000602082019050613f6e6000830184613822565b92915050565b6000602082019050613f896000830184613c49565b92915050565b600060208284031215613fa557613fa4612ec7565b5b6000613fb3848285016130e4565b91505092915050565b6000602082019050613fd16000830184613e4e565b92915050565b6000602082019050613fec6000830184613c6a565b92915050565b613ffb816132a8565b82525050565b60a0820160008201516140176000850182613679565b50602082015161402a6020850182613679565b50604082015161403d6040850182613679565b5060608201516140506060850182613679565b5060808201516140636080850182613ff2565b50505050565b600060a08201905061407e6000830184614001565b92915050565b600061408f8261378e565b9050919050565b61409f81614084565b82525050565b60006020820190506140ba6000830184614096565b92915050565b60006040820190506140d56000830185613822565b6140e26020830184613822565b9392505050565b6000602082840312156140ff576140fe612ec7565b5b600061410d848285016138d8565b91505092915050565b600067ffffffffffffffff82111561413157614130612eec565b5b602082029050602081019050919050565b600061415561415084614116565b612f4c565b9050808382526020820190506020840283018581111561417857614177613125565b5b835b818110156141a1578061418d88826138d8565b84526020840193505060208101905061417a565b5050509392505050565b600082601f8301126141c0576141bf612ed1565b5b81356141d0848260208601614142565b91505092915050565b600080600080608085870312156141f3576141f2612ec7565b5b600085013567ffffffffffffffff81111561421157614210612ecc565b5b61421d878288016141ab565b945050602085013567ffffffffffffffff81111561423e5761423d612ecc565b5b61424a87828801612fe9565b935050604085013567ffffffffffffffff81111561426b5761426a612ecc565b5b61427787828801613982565b925050606085013567ffffffffffffffff81111561429857614297612ecc565b5b6142a4878288016131bf565b91505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60006142e88383613ff2565b60208301905092915050565b6000602082019050919050565b600061430c826142b0565b61431681856142bb565b9350614321836142cc565b8060005b8381101561435257815161433988826142dc565b9750614344836142f4565b925050600181019050614325565b5085935050505092915050565b600060208201905081810360008301526143798184614301565b905092915050565b6000806040838503121561439857614397612ec7565b5b60006143a6858286016130e4565b92505060206143b7858286016130e4565b9150509250929050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff82169050919050565b6143f2816143c1565b82525050565b600060408201905061440d60008301856143e9565b61441a6020830184613c49565b9392505050565b6000806000806080858703121561443b5761443a612ec7565b5b600061444987828801613141565b945050602061445a87828801613a00565b935050604061446b87828801613141565b925050606061447c87828801613141565b91505092959194509250565b60408201600082015161449e6000850182613379565b5060208201516144b16020850182613679565b50505050565b60006040820190506144cc6000830184614488565b92915050565b6144db81613c58565b81146144e657600080fd5b50565b6000813590506144f8816144d2565b92915050565b60006020828403121561451457614513612ec7565b5b6000614522848285016144e9565b91505092915050565b600081905092915050565b60006145418261342d565b61454b818561452b565b935061455b818560208601613449565b80840191505092915050565b60006145738285614536565b915061457f8284614536565b91508190509392505050565b7f436861696e000000000000000000000000000000000000000000000000000000815250565b60006020820190506145c56000830161458b565b919050565b6000815190506145d9816144d2565b92915050565b6000602082840312156145f5576145f4612ec7565b5b6000614603848285016145ca565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008160e01b9050919050565b60006146538261463b565b9050919050565b61466b61466682613669565b614648565b82525050565b6000819050919050565b61468c6146878261308f565b614671565b82525050565b600061469e828561465a565b6004820191506146ae828461467b565b6020820191508190509392505050565b6000819050919050565b6146d96146d4826130c3565b6146be565b82525050565b60006146eb8286614536565b91506146f7828561467b565b60208201915061470782846146c8565b602082019150819050949350505050565b600081519050614727816130cd565b92915050565b60006020828403121561474357614742612ec7565b5b600061475184828501614718565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614794826130c3565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036147c6576147c561475a565b5b600182019050919050565b60006147ec6147e76147e284613669565b613762565b6130c3565b9050919050565b6147fc816147d1565b82525050565b600060608201905061481760008301866147f3565b6148246020830185613822565b6148316040830184613822565b949350505050565b600082825260208201905092915050565b7f5f726567697374727920697320656d7074790000000000000000000000000000600082015250565b6000614880601283614839565b915061488b8261484a565b602082019050919050565b600060208201905081810360008301526148af81614873565b9050919050565b7f554d420000000000000000000000000000000000000000000000000000000000815250565b60006020820190506148f0600083016148b6565b919050565b7f5374616b696e6742616e6b000000000000000000000000000000000000000000815250565b600060208201905061492f600083016148f5565b919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600061496a602083614839565b915061497582614934565b602082019050919050565b600060208201905081810360008301526149998161495d565b9050919050565b60006149ab82613669565b91506149b683613669565b9250828210156149c9576149c861475a565b5b828203905092915050565b60006149df826130c3565b91506149ea836130c3565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115614a1f57614a1e61475a565b5b828201905092915050565b6000614a368285614536565b9150614a42828461467b565b6020820191508190509392505050565b614a5b816139dc565b82525050565b6000608082019050614a766000830187613099565b614a836020830186614a52565b614a906040830185613099565b614a9d6060830184613099565b95945050505050565b614aaf816132a8565b8114614aba57600080fd5b50565b600081519050614acc81614aa6565b92915050565b600060208284031215614ae857614ae7612ec7565b5b6000614af684828501614abd565b91505092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000614b5b602683614839565b9150614b6682614aff565b604082019050919050565b60006020820190508181036000830152614b8a81614b4e565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b614bc681614b91565b82525050565b6000602082019050614be16000830184614bbd565b92915050565b6000614bf38284614536565b915081905092915050565b600081519050614c0d816138c1565b92915050565b600060208284031215614c2957614c28612ec7565b5b6000614c3784828501614bfe565b91505092915050565b6000614c4b82613669565b9150614c5683613669565b92508263ffffffff03821115614c6f57614c6e61475a565b5b828201905092915050565b600080fd5b600060a08284031215614c9557614c94614c7a565b5b614c9f60a0612f4c565b90506000614caf84828501614bfe565b6000830152506020614cc384828501614bfe565b6020830152506040614cd784828501614bfe565b6040830152506060614ceb84828501614bfe565b6060830152506080614cff84828501614abd565b60808301525092915050565b600060a08284031215614d2157614d20612ec7565b5b6000614d2f84828501614c7f565b91505092915050565b6000614d43826143c1565b9150614d4e836143c1565b925082821015614d6157614d6061475a565b5b828203905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614da6826143c1565b9150614db1836143c1565b925082614dc157614dc0614d6c565b5b82820490509291505056fea2646970667358221220c360ae03d3a676b33b3c5097d3c8e8893865decc08d54266712bbb98da90469d64736f6c634300080d0033", "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101f95760003560e01c80630f2acc3e146101fe5780630fcc0c281461022e57806317d7de7c14610238578063199dadc5146102565780631aa3a00814610286578063243b68f91461029057806324c89a49146102c057806326f3ab8b146102de57806334ba34811461030f5780633bb8819d1461032d57806340a9e5e31461035e578063485e055d1461037a5780634bc935d7146103965780634e69d560146103c657806355a373d6146103ee578063637180a81461040c5780636d046c3e1461042a578063715018a6146104485780637353cbcb1461045257806377839fe614610470578063805d34321461048e5780638d068043146104be5780638da5cb5b146104dc5780639f6119d7146104fa578063a0bc937414610518578063abf410e514610536578063adf1639d14610554578063bef9f8a114610585578063bf66e3ba146105b5578063c2a4250b146105e5578063c2b40ae414610603578063c3369db814610633578063ca4d29d214610663578063cbb1b2c714610693578063d3d3ea08146106c4578063d45167d0146106e2578063e76c0b5714610712578063e79a198f14610730578063ed9975c31461073a578063ef19f3e714610758578063f25b3f9914610788578063f2fde38b146107b8578063ffa1ad74146107d4575b600080fd5b61021860048036038101906102139190613017565b6107f2565b60405161022591906130a8565b60405180910390f35b610236610825565b005b610240610997565b60405161024d91906130a8565b60405180910390f35b610270600480360381019061026b91906131ed565b6109bf565b60405161027d91906132c3565b60405180910390f35b61028e610a1b565b005b6102aa60048036038101906102a591906132de565b610c29565b6040516102b7919061340b565b60405180910390f35b6102c8610cd2565b6040516102d591906134b5565b60405180910390f35b6102f860048036038101906102f39190613532565b610d0b565b60405161030692919061370b565b60405180910390f35b610317610eaa565b60405161032491906137c1565b60405180910390f35b610347600480360381019061034291906137dc565b610ece565b604051610355929190613831565b60405180910390f35b61037860048036038101906103739190613894565b610f63565b005b610394600480360381019061038f9190613aac565b610f73565b005b6103b060048036038101906103ab9190613bda565b611546565b6040516103bd91906132c3565b60405180910390f35b6103ce61157a565b6040516103e59b9a99989796959493929190613e5d565b60405180910390f35b6103f661181e565b6040516104039190613f3e565b60405180910390f35b61041461194b565b60405161042191906137c1565b60405180910390f35b6104326119ea565b60405161043f91906132c3565b60405180910390f35b6104506119f3565b005b61045a611a7b565b6040516104679190613f59565b60405180910390f35b610478611abe565b6040516104859190613f74565b60405180910390f35b6104a860048036038101906104a39190613f8f565b611adb565b6040516104b59190613f74565b60405180910390f35b6104c6611bcf565b6040516104d39190613fbc565b60405180910390f35b6104e4611bf7565b6040516104f19190613fd7565b60405180910390f35b610502611c20565b60405161050f9190613fd7565b60405180910390f35b610520611c3c565b60405161052d9190614069565b60405180910390f35b61053e611d09565b60405161054b91906140a5565b60405180910390f35b61056e600480360381019061056991906137dc565b611d2d565b60405161057c9291906140c0565b60405180910390f35b61059f600480360381019061059a91906140e9565b611dba565b6040516105ac91906130a8565b60405180910390f35b6105cf60048036038101906105ca91906141d9565b611ddd565b6040516105dc919061435f565b60405180910390f35b6105ed611f19565b6040516105fa9190613f59565b60405180910390f35b61061d60048036038101906106189190613f8f565b611f3c565b60405161062a91906130a8565b60405180910390f35b61064d600480360381019061064891906140e9565b611f54565b60405161065a9190613f74565b60405180910390f35b61067d60048036038101906106789190614381565b611f89565b60405161068a9190613f59565b60405180910390f35b6106ad60048036038101906106a891906137dc565b611fbd565b6040516106bb9291906143f8565b60405180910390f35b6106cc612019565b6040516106d99190613f74565b60405180910390f35b6106fc60048036038101906106f79190614421565b612036565b6040516107099190613fd7565b60405180910390f35b61071a6120f3565b6040516107279190613f74565b60405180910390f35b61073861212f565b005b6107426124b0565b60405161074f9190613fd7565b60405180910390f35b610772600480360381019061076d9190613f8f565b6124c0565b60405161077f9190613fd7565b60405180910390f35b6107a2600480360381019061079d9190613f8f565b6124f4565b6040516107af91906144b7565b60405180910390f35b6107d260048036038101906107cd91906144fe565b612531565b005b6107dc612628565b6040516107e99190613f59565b60405180910390f35b60008282604051602001610807929190614567565b60405160208183030381529060405280519060200120905092915050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156108b45750610884611bf7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156108eb576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160000160109054906101000a900460ff1615610935576040517f764c143b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018060000160106101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167fd4ae81319f0b4df100dcda9ce971671b97278c7a5ce6b37a8331a44700679fd460405160405180910390a2565b60007f436861696e000000000000000000000000000000000000000000000000000000905090565b6000610a11600260008781526020019081526020016000205484846040516020016109eb929190614567565b604051602081830303815290604052805190602001208661262d9092919063ffffffff16565b9050949350505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015610aaa5750610a7a611bf7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15610ae1576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b8152600401610b3a906145b1565b602060405180830381865afa158015610b57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7b91906145df565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610be2576040517f3a81d6fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610c1c5750610c27565b610c2581612644565b505b565b606060008267ffffffffffffffff811115610c4757610c46612eec565b5b604051908082528060200260200182016040528015610c755781602001602082028036833780820191505090505b50905060005b83811015610cc657600080602087600185010102905080880151915081848481518110610cab57610caa61460c565b5b60200260200101818152505050508080600101915050610c7b565b50809150509392505050565b6040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525081565b6060808383905067ffffffffffffffff811115610d2b57610d2a612eec565b5b604051908082528060200260200182016040528015610d595781602001602082028036833780820191505090505b5090508383905067ffffffffffffffff811115610d7957610d78612eec565b5b604051908082528060200260200182016040528015610da75781602001602082028036833780820191505090505b50915060005b84849050811015610ea257600060036000878785818110610dd157610dd061460c565b5b90506020020135815260200190815260200160002090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16848381518110610e4657610e4561460c565b5b60200260200101818152505080600001601c9054906101000a900463ffffffff16838381518110610e7a57610e7961460c565b5b602002602001019063ffffffff16908163ffffffff1681525050818060010192505050610dad565b509250929050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806000600360008581526020019081526020016000209050610f3b8160000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16612986565b81600001601c9054906101000a900463ffffffff168063ffffffff1690509250925050915091565b610f708161ffff16612a2e565b50565b610f828763ffffffff16612b79565b60008787604051602001610f97929190614692565b604051602081830303815290604052905060005b86518110156111a757858181518110610fc757610fc661460c565b5b6020026020010151868281518110610fe257610fe161460c565b5b60200260200101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff161461103f576040517f6980091000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604051806040016040528087838151811061105d5761105c61460c565b5b60200260200101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681526020018a63ffffffff16815250600360008984815181106110a9576110a861460c565b5b6020026020010151815260200190815260200160002060008201518160000160006101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff160217905550602082015181600001601c6101000a81548163ffffffff021916908363ffffffff160217905550905050818782815181106111545761115361460c565b5b602002602001015187838151811061116f5761116e61460c565b5b6020026020010151604051602001611189939291906146df565b60405160208183030381529060405291508080600101915050610fab565b506000806000838051906020012090506000805b88518110156113b7576000611220848b84815181106111dd576111dc61460c565b5b60200260200101518b85815181106111f8576111f761460c565b5b60200260200101518b86815181106112135761121261460c565b5b6020026020010151612036565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231836040518263ffffffff1660e01b815260040161127d9190613fd7565b602060405180830381865afa15801561129a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112be919061472d565b90508173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1610611325576040517f9079f69b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8193506000810361133f57828060010193505050506113b2565b868061134a90614789565b9750508173ffffffffffffffffffffffffffffffffffffffff168f63ffffffff167fbac7552ab5da8d0588709ddb75aceec28520646f54bca1cc5e6e104db61935ec8360405161139a9190613f59565b60405180910390a38086019550828060010193505050505b6111bb565b507f000000000000000000000000000000000000000000000000000000000000000061ffff16841015611416576040517fe246dc6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167f5f11830295067c4bcc7d02d4e3b048cd7427be50a3aeb6afc9d3d559ee64bcfa8d7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114de919061472d565b866040516114ee93929190614802565b60405180910390a28a600260008e63ffffffff168152602001908152602001600020819055508b600160000160086101000a81548163ffffffff021916908363ffffffff160217905550505050505050505050505050565b60008060001b830361155b5760009050611573565b61157083838661262d9092919063ffffffff16565b90505b9392505050565b6000806000806000806060806060600080600060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff1615151515815250509050439b5080606001519a50806040015198508899507f000000000000000000000000000000000000000000000000000000000000000091507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611715919061472d565b925060008067ffffffffffffffff81111561173357611732612eec565b5b6040519080825280602002602001820160405280156117615781602001602082028036833780820191505090505b5095508067ffffffffffffffff81111561177e5761177d612eec565b5b6040519080825280602002602001820160405280156117ac5781602001602082028036833780820191505090505b5096508067ffffffffffffffff8111156117c9576117c8612eec565b5b6040519080825280602002602001820160405280156117fc57816020015b60608152602001906001900390816117e75790505b50945060009850600182606001518b010197505050909192939495969798999a565b60008073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16036118ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118a590614896565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b8152600401611905906148dc565b602060405180830381865afa158015611922573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194691906145df565b905090565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b81526004016119a49061491b565b602060405180830381865afa1580156119c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e591906145df565b905090565b60006001905090565b6119fb612cf9565b73ffffffffffffffffffffffffffffffffffffffff16611a19611bf7565b73ffffffffffffffffffffffffffffffffffffffff1614611a6f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a6690614980565b60405180910390fd5b611a796000612d01565b565b6000600160000160009054906101000a900463ffffffff16600160000160049054906101000a900463ffffffff16611ab391906149a0565b63ffffffff16905090565b6000600160000160009054906101000a900463ffffffff16905090565b60008060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff161515151581525050905082816060015182604001510163ffffffff161015611bc15782915050611bca565b80604001519150505b919050565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000611c37600142611c3291906149d4565b6124c0565b905090565b611c44612e51565b60016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff161515151581525050905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060006003600085815260200190815260200160002090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681600001601c9054906101000a900463ffffffff168063ffffffff1690509250925050915091565b6000600260008363ffffffff168152602001908152602001600020549050919050565b6060815167ffffffffffffffff811115611dfa57611df9612eec565b5b604051908082528060200260200182016040528015611e285781602001602082028036833780820191505090505b5090506000805b8351811015611f0f57611ebe60026000898481518110611e5257611e5161460c565b5b602002602001015163ffffffff16815260200190815260200160002054858381518110611e8257611e8161460c565b5b6020026020010151611eaf89868a8781518110611ea257611ea161460c565b5b6020026020010151610c29565b61262d9092919063ffffffff16565b838281518110611ed157611ed061460c565b5b602002602001019015159081151581525050848181518110611ef657611ef561460c565b5b6020026020010151820191508080600101915050611e2f565b5050949350505050565b6000600160000160089054906101000a900463ffffffff1663ffffffff16905090565b60026020528060005260406000206000915090505481565b60008060001b600260008463ffffffff1681526020019081526020016000205414611f7f5781611f82565b60005b9050919050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60036020528060005260406000206000915090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169080600001601c9054906101000a900463ffffffff16905082565b6000600160000160089054906101000a900463ffffffff16905090565b6000806040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525086604051602001612081929190614a2a565b604051602081830303815290604052805190602001209050600181868686604051600081526020016040526040516120bc9493929190614a61565b6020604051602081039080840390855afa1580156120de573d6000803e3d6000fd5b50505060206040510351915050949350505050565b600080600160000160089054906101000a900463ffffffff1663ffffffff1603612120576000905061212c565b61212942611adb565b90505b90565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156121be575061218e611bf7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156121f5576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160000160109054906101000a900460ff166124ae5760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b8152600401612265906145b1565b602060405180830381865afa158015612282573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122a691906145df565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361230d576040517ff8e0084400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061244c573073ffffffffffffffffffffffffffffffffffffffff16636d046c3e6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561237d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123a19190614ad2565b15158173ffffffffffffffffffffffffffffffffffffffff16636d046c3e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124129190614ad2565b15151461244b576040517f07b72f5e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b60018060000160106101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167fd4ae81319f0b4df100dcda9ce971671b97278c7a5ce6b37a8331a44700679fd460405160405180910390a2505b565b60006124bb426124c0565b905090565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6124fc612e9a565b6040518060400160405280600260008581526020019081526020016000205481526020018363ffffffff168152509050919050565b612539612cf9565b73ffffffffffffffffffffffffffffffffffffffff16612557611bf7565b73ffffffffffffffffffffffffffffffffffffffff16146125ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125a490614980565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361261c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161261390614b71565b60405180910390fd5b61262581612d01565b50565b600281565b60008261263a8584612dc5565b1490509392505050565b6000808273ffffffffffffffffffffffffffffffffffffffff167fffa1ad74ba96b4c159a84d090433911c3991c54f629eb60d0c84aed3be5f067c60405160200161268f9190614bcc565b6040516020818303038152906040526040516126ab9190614be7565b600060405180830381855afa9150503d80600081146126e6576040519150601f19603f3d011682016040523d82523d6000602084013e6126eb565b606091505b50915091506000826126fe576001612713565b81806020019051810190612712919061472d565b5b9050600181036128935760008473ffffffffffffffffffffffffffffffffffffffff1663d3d3ea086040518163ffffffff1660e01b8152600401602060405180830381865afa15801561276a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061278e9190614c13565b90508473ffffffffffffffffffffffffffffffffffffffff1663c3369db8826040518263ffffffff1660e01b81526004016127c99190613f74565b602060405180830381865afa1580156127e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061280a9190614c13565b600160000160086101000a81548163ffffffff021916908363ffffffff16021790555060028161283a9190614c40565b600160000160046101000a81548163ffffffff021916908363ffffffff16021790555060028161286a9190614c40565b600160000160006101000a81548163ffffffff021916908363ffffffff16021790555050612980565b60008473ffffffffffffffffffffffffffffffffffffffff1663a0bc93746040518163ffffffff1660e01b815260040160a060405180830381865afa1580156128e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129049190614d0b565b90508060200151600160000160046101000a81548163ffffffff021916908363ffffffff1602179055508060200151600160000160006101000a81548163ffffffff021916908363ffffffff1602179055508060400151600160000160086101000a81548163ffffffff021916908363ffffffff160217905550505b50505050565b60008060007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff905060026001826129b99190614d38565b6129c39190614d9b565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1611612a185760008401915081601b0b92505050612a29565b600181850303915081601b0b925050505b919050565b612a36612cf9565b73ffffffffffffffffffffffffffffffffffffffff16612a54611bf7565b73ffffffffffffffffffffffffffffffffffffffff1614612aaa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612aa190614980565b60405180910390fd5b8063ffffffff166001600001600c9054906101000a900463ffffffff1663ffffffff1603612b04576040517f96f56f6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600001600c6101000a81548163ffffffff021916908363ffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167f02ff77a0f68d11f7efb906f331b2dda82916de8ba9c37dda2a95817936a530ec82604051612b6e9190613f74565b60405180910390a250565b600060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff16151515158152505090506000816040015163ffffffff1603612c81576040517f96a96e1700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81816060015182604001510163ffffffff1610612cca576040517ff886149e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001816020015101600160000160046101000a81548163ffffffff021916908363ffffffff1602179055505050565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60008082905060005b8451811015612e2f576000858281518110612dec57612deb61460c565b5b60200260200101519050808311612e0e57612e078382612e3a565b9250612e1b565b612e188184612e3a565b92505b508080612e2790614789565b915050612dce565b508091505092915050565b600082600052816020526040600020905092915050565b6040518060a00160405280600063ffffffff168152602001600063ffffffff168152602001600063ffffffff168152602001600063ffffffff1681526020016000151581525090565b604051806040016040528060008019168152602001600063ffffffff1681525090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612f2482612edb565b810181811067ffffffffffffffff82111715612f4357612f42612eec565b5b80604052505050565b6000612f56612ebd565b9050612f628282612f1b565b919050565b600067ffffffffffffffff821115612f8257612f81612eec565b5b612f8b82612edb565b9050602081019050919050565b82818337600083830152505050565b6000612fba612fb584612f67565b612f4c565b905082815260208101848484011115612fd657612fd5612ed6565b5b612fe1848285612f98565b509392505050565b600082601f830112612ffe57612ffd612ed1565b5b813561300e848260208601612fa7565b91505092915050565b6000806040838503121561302e5761302d612ec7565b5b600083013567ffffffffffffffff81111561304c5761304b612ecc565b5b61305885828601612fe9565b925050602083013567ffffffffffffffff81111561307957613078612ecc565b5b61308585828601612fe9565b9150509250929050565b6000819050919050565b6130a28161308f565b82525050565b60006020820190506130bd6000830184613099565b92915050565b6000819050919050565b6130d6816130c3565b81146130e157600080fd5b50565b6000813590506130f3816130cd565b92915050565b600067ffffffffffffffff82111561311457613113612eec565b5b602082029050602081019050919050565b600080fd5b6131338161308f565b811461313e57600080fd5b50565b6000813590506131508161312a565b92915050565b6000613169613164846130f9565b612f4c565b9050808382526020820190506020840283018581111561318c5761318b613125565b5b835b818110156131b557806131a18882613141565b84526020840193505060208101905061318e565b5050509392505050565b600082601f8301126131d4576131d3612ed1565b5b81356131e4848260208601613156565b91505092915050565b6000806000806080858703121561320757613206612ec7565b5b6000613215878288016130e4565b945050602085013567ffffffffffffffff81111561323657613235612ecc565b5b613242878288016131bf565b935050604085013567ffffffffffffffff81111561326357613262612ecc565b5b61326f87828801612fe9565b925050606085013567ffffffffffffffff8111156132905761328f612ecc565b5b61329c87828801612fe9565b91505092959194509250565b60008115159050919050565b6132bd816132a8565b82525050565b60006020820190506132d860008301846132b4565b92915050565b6000806000606084860312156132f7576132f6612ec7565b5b600084013567ffffffffffffffff81111561331557613314612ecc565b5b61332186828701612fe9565b9350506020613332868287016130e4565b9250506040613343868287016130e4565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6133828161308f565b82525050565b60006133948383613379565b60208301905092915050565b6000602082019050919050565b60006133b88261334d565b6133c28185613358565b93506133cd83613369565b8060005b838110156133fe5781516133e58882613388565b97506133f0836133a0565b9250506001810190506133d1565b5085935050505092915050565b6000602082019050818103600083015261342581846133ad565b905092915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561346757808201518184015260208101905061344c565b83811115613476576000848401525b50505050565b60006134878261342d565b6134918185613438565b93506134a1818560208601613449565b6134aa81612edb565b840191505092915050565b600060208201905081810360008301526134cf818461347c565b905092915050565b600080fd5b60008083601f8401126134f2576134f1612ed1565b5b8235905067ffffffffffffffff81111561350f5761350e6134d7565b5b60208301915083602082028301111561352b5761352a613125565b5b9250929050565b6000806020838503121561354957613548612ec7565b5b600083013567ffffffffffffffff81111561356757613566612ecc565b5b613573858286016134dc565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6135b4816130c3565b82525050565b60006135c683836135ab565b60208301905092915050565b6000602082019050919050565b60006135ea8261357f565b6135f4818561358a565b93506135ff8361359b565b8060005b8381101561363057815161361788826135ba565b9750613622836135d2565b925050600181019050613603565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600063ffffffff82169050919050565b61368281613669565b82525050565b60006136948383613679565b60208301905092915050565b6000602082019050919050565b60006136b88261363d565b6136c28185613648565b93506136cd83613659565b8060005b838110156136fe5781516136e58882613688565b97506136f0836136a0565b9250506001810190506136d1565b5085935050505092915050565b6000604082019050818103600083015261372581856135df565b9050818103602083015261373981846136ad565b90509392505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061378761378261377d84613742565b613762565b613742565b9050919050565b60006137998261376c565b9050919050565b60006137ab8261378e565b9050919050565b6137bb816137a0565b82525050565b60006020820190506137d660008301846137b2565b92915050565b6000602082840312156137f2576137f1612ec7565b5b600061380084828501613141565b91505092915050565b6000819050919050565b61381c81613809565b82525050565b61382b816130c3565b82525050565b60006040820190506138466000830185613813565b6138536020830184613822565b9392505050565b600061ffff82169050919050565b6138718161385a565b811461387c57600080fd5b50565b60008135905061388e81613868565b92915050565b6000602082840312156138aa576138a9612ec7565b5b60006138b88482850161387f565b91505092915050565b6138ca81613669565b81146138d557600080fd5b50565b6000813590506138e7816138c1565b92915050565b600067ffffffffffffffff82111561390857613907612eec565b5b602082029050602081019050919050565b600061392c613927846138ed565b612f4c565b9050808382526020820190506020840283018581111561394f5761394e613125565b5b835b81811015613978578061396488826130e4565b845260208401935050602081019050613951565b5050509392505050565b600082601f83011261399757613996612ed1565b5b81356139a7848260208601613919565b91505092915050565b600067ffffffffffffffff8211156139cb576139ca612eec565b5b602082029050602081019050919050565b600060ff82169050919050565b6139f2816139dc565b81146139fd57600080fd5b50565b600081359050613a0f816139e9565b92915050565b6000613a28613a23846139b0565b612f4c565b90508083825260208201905060208402830185811115613a4b57613a4a613125565b5b835b81811015613a745780613a608882613a00565b845260208401935050602081019050613a4d565b5050509392505050565b600082601f830112613a9357613a92612ed1565b5b8135613aa3848260208601613a15565b91505092915050565b600080600080600080600060e0888a031215613acb57613aca612ec7565b5b6000613ad98a828b016138d8565b9750506020613aea8a828b01613141565b965050604088013567ffffffffffffffff811115613b0b57613b0a612ecc565b5b613b178a828b016131bf565b955050606088013567ffffffffffffffff811115613b3857613b37612ecc565b5b613b448a828b01613982565b945050608088013567ffffffffffffffff811115613b6557613b64612ecc565b5b613b718a828b01613a7e565b93505060a088013567ffffffffffffffff811115613b9257613b91612ecc565b5b613b9e8a828b016131bf565b92505060c088013567ffffffffffffffff811115613bbf57613bbe612ecc565b5b613bcb8a828b016131bf565b91505092959891949750929550565b600080600060608486031215613bf357613bf2612ec7565b5b600084013567ffffffffffffffff811115613c1157613c10612ecc565b5b613c1d868287016131bf565b9350506020613c2e86828701613141565b9250506040613c3f86828701613141565b9150509250925092565b613c5281613669565b82525050565b6000613c6382613742565b9050919050565b613c7381613c58565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b613cae81613c58565b82525050565b6000613cc08383613ca5565b60208301905092915050565b6000602082019050919050565b6000613ce482613c79565b613cee8185613c84565b9350613cf983613c95565b8060005b83811015613d2a578151613d118882613cb4565b9750613d1c83613ccc565b925050600181019050613cfd565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b6000613d8a82613d63565b613d948185613d6e565b9350613da4818560208601613449565b613dad81612edb565b840191505092915050565b6000613dc48383613d7f565b905092915050565b6000602082019050919050565b6000613de482613d37565b613dee8185613d42565b935083602082028501613e0085613d53565b8060005b85811015613e3c5784840389528151613e1d8582613db8565b9450613e2883613dcc565b925060208a01995050600181019050613e04565b50829750879550505050505092915050565b613e578161385a565b82525050565b600061016082019050613e73600083018e613822565b613e80602083018d613c49565b613e8d604083018c613c49565b613e9a606083018b613c49565b613ea7608083018a613c6a565b613eb460a0830189613c49565b81810360c0830152613ec68188613cd9565b905081810360e0830152613eda81876135df565b9050818103610100830152613eef8186613dd9565b9050613eff610120830185613822565b613f0d610140830184613e4e565b9c9b505050505050505050505050565b6000613f288261378e565b9050919050565b613f3881613f1d565b82525050565b6000602082019050613f536000830184613f2f565b92915050565b6000602082019050613f6e6000830184613822565b92915050565b6000602082019050613f896000830184613c49565b92915050565b600060208284031215613fa557613fa4612ec7565b5b6000613fb3848285016130e4565b91505092915050565b6000602082019050613fd16000830184613e4e565b92915050565b6000602082019050613fec6000830184613c6a565b92915050565b613ffb816132a8565b82525050565b60a0820160008201516140176000850182613679565b50602082015161402a6020850182613679565b50604082015161403d6040850182613679565b5060608201516140506060850182613679565b5060808201516140636080850182613ff2565b50505050565b600060a08201905061407e6000830184614001565b92915050565b600061408f8261378e565b9050919050565b61409f81614084565b82525050565b60006020820190506140ba6000830184614096565b92915050565b60006040820190506140d56000830185613822565b6140e26020830184613822565b9392505050565b6000602082840312156140ff576140fe612ec7565b5b600061410d848285016138d8565b91505092915050565b600067ffffffffffffffff82111561413157614130612eec565b5b602082029050602081019050919050565b600061415561415084614116565b612f4c565b9050808382526020820190506020840283018581111561417857614177613125565b5b835b818110156141a1578061418d88826138d8565b84526020840193505060208101905061417a565b5050509392505050565b600082601f8301126141c0576141bf612ed1565b5b81356141d0848260208601614142565b91505092915050565b600080600080608085870312156141f3576141f2612ec7565b5b600085013567ffffffffffffffff81111561421157614210612ecc565b5b61421d878288016141ab565b945050602085013567ffffffffffffffff81111561423e5761423d612ecc565b5b61424a87828801612fe9565b935050604085013567ffffffffffffffff81111561426b5761426a612ecc565b5b61427787828801613982565b925050606085013567ffffffffffffffff81111561429857614297612ecc565b5b6142a4878288016131bf565b91505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60006142e88383613ff2565b60208301905092915050565b6000602082019050919050565b600061430c826142b0565b61431681856142bb565b9350614321836142cc565b8060005b8381101561435257815161433988826142dc565b9750614344836142f4565b925050600181019050614325565b5085935050505092915050565b600060208201905081810360008301526143798184614301565b905092915050565b6000806040838503121561439857614397612ec7565b5b60006143a6858286016130e4565b92505060206143b7858286016130e4565b9150509250929050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff82169050919050565b6143f2816143c1565b82525050565b600060408201905061440d60008301856143e9565b61441a6020830184613c49565b9392505050565b6000806000806080858703121561443b5761443a612ec7565b5b600061444987828801613141565b945050602061445a87828801613a00565b935050604061446b87828801613141565b925050606061447c87828801613141565b91505092959194509250565b60408201600082015161449e6000850182613379565b5060208201516144b16020850182613679565b50505050565b60006040820190506144cc6000830184614488565b92915050565b6144db81613c58565b81146144e657600080fd5b50565b6000813590506144f8816144d2565b92915050565b60006020828403121561451457614513612ec7565b5b6000614522848285016144e9565b91505092915050565b600081905092915050565b60006145418261342d565b61454b818561452b565b935061455b818560208601613449565b80840191505092915050565b60006145738285614536565b915061457f8284614536565b91508190509392505050565b7f436861696e000000000000000000000000000000000000000000000000000000815250565b60006020820190506145c56000830161458b565b919050565b6000815190506145d9816144d2565b92915050565b6000602082840312156145f5576145f4612ec7565b5b6000614603848285016145ca565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008160e01b9050919050565b60006146538261463b565b9050919050565b61466b61466682613669565b614648565b82525050565b6000819050919050565b61468c6146878261308f565b614671565b82525050565b600061469e828561465a565b6004820191506146ae828461467b565b6020820191508190509392505050565b6000819050919050565b6146d96146d4826130c3565b6146be565b82525050565b60006146eb8286614536565b91506146f7828561467b565b60208201915061470782846146c8565b602082019150819050949350505050565b600081519050614727816130cd565b92915050565b60006020828403121561474357614742612ec7565b5b600061475184828501614718565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614794826130c3565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036147c6576147c561475a565b5b600182019050919050565b60006147ec6147e76147e284613669565b613762565b6130c3565b9050919050565b6147fc816147d1565b82525050565b600060608201905061481760008301866147f3565b6148246020830185613822565b6148316040830184613822565b949350505050565b600082825260208201905092915050565b7f5f726567697374727920697320656d7074790000000000000000000000000000600082015250565b6000614880601283614839565b915061488b8261484a565b602082019050919050565b600060208201905081810360008301526148af81614873565b9050919050565b7f554d420000000000000000000000000000000000000000000000000000000000815250565b60006020820190506148f0600083016148b6565b919050565b7f5374616b696e6742616e6b000000000000000000000000000000000000000000815250565b600060208201905061492f600083016148f5565b919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600061496a602083614839565b915061497582614934565b602082019050919050565b600060208201905081810360008301526149998161495d565b9050919050565b60006149ab82613669565b91506149b683613669565b9250828210156149c9576149c861475a565b5b828203905092915050565b60006149df826130c3565b91506149ea836130c3565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115614a1f57614a1e61475a565b5b828201905092915050565b6000614a368285614536565b9150614a42828461467b565b6020820191508190509392505050565b614a5b816139dc565b82525050565b6000608082019050614a766000830187613099565b614a836020830186614a52565b614a906040830185613099565b614a9d6060830184613099565b95945050505050565b614aaf816132a8565b8114614aba57600080fd5b50565b600081519050614acc81614aa6565b92915050565b600060208284031215614ae857614ae7612ec7565b5b6000614af684828501614abd565b91505092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000614b5b602683614839565b9150614b6682614aff565b604082019050919050565b60006020820190508181036000830152614b8a81614b4e565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b614bc681614b91565b82525050565b6000602082019050614be16000830184614bbd565b92915050565b6000614bf38284614536565b915081905092915050565b600081519050614c0d816138c1565b92915050565b600060208284031215614c2957614c28612ec7565b5b6000614c3784828501614bfe565b91505092915050565b6000614c4b82613669565b9150614c5683613669565b92508263ffffffff03821115614c6f57614c6e61475a565b5b828201905092915050565b600080fd5b600060a08284031215614c9557614c94614c7a565b5b614c9f60a0612f4c565b90506000614caf84828501614bfe565b6000830152506020614cc384828501614bfe565b6020830152506040614cd784828501614bfe565b6040830152506060614ceb84828501614bfe565b6060830152506080614cff84828501614abd565b60808301525092915050565b600060a08284031215614d2157614d20612ec7565b5b6000614d2f84828501614c7f565b91505092915050565b6000614d43826143c1565b9150614d4e836143c1565b925082821015614d6157614d6061475a565b5b828203905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614da6826143c1565b9150614db1836143c1565b925082614dc157614dc0614d6c565b5b82820490509291505056fea2646970667358221220c360ae03d3a676b33b3c5097d3c8e8893865decc08d54266712bbb98da90469d64736f6c634300080d0033", diff --git a/deployments/polygon_production/StakingBankStatic.json b/deployments/polygon_production/StakingBankStatic.json index 08c93be2..3d234add 100644 --- a/deployments/polygon_production/StakingBankStatic.json +++ b/deployments/polygon_production/StakingBankStatic.json @@ -1,5 +1,5 @@ { - "address": "0x846F52020749715F02AEf25b5d1d65e48945649D", + "address": "0x9272e064766e824C8eB8D04F507d2fae7f1aA9D6", "abi": [ { "inputs": [ @@ -249,58 +249,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "VALIDATOR_15", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATOR_16", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATOR_17", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATOR_18", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "VALIDATOR_2", @@ -812,46 +760,46 @@ "type": "function" } ], - "transactionHash": "0xcf3df608c1281faefc26d748439397600d37bfe3621dd727f0968b9b9b9f9b80", + "transactionHash": "0xc23938703c67a2d8159a0d161e22d712d6a8ee81590b19ba17bf900863f31e61", "receipt": { "to": null, "from": "0xA6e4fFa19B213AbeA258ae72e8e1a209B9E543e7", - "contractAddress": "0x846F52020749715F02AEf25b5d1d65e48945649D", - "transactionIndex": 45, - "gasUsed": "2643132", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000008000000000000000800000000000000000000100000000000000000000000000000000000000000000000000000800100080000000000020000000000000000000000000000000000000000000000000000002000000000000200000000000000000000000000000000000000000000000010000000000004000000000000000000001000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000", - "blockHash": "0xb244c634b14958cb2fedea7470e4ccdcadeac1f4c7e49b730421fae11c167d63", - "transactionHash": "0xcf3df608c1281faefc26d748439397600d37bfe3621dd727f0968b9b9b9f9b80", + "contractAddress": "0x9272e064766e824C8eB8D04F507d2fae7f1aA9D6", + "transactionIndex": 65, + "gasUsed": "2301671", + "logsBloom": "0x00000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000800000000000000000000100000000000000000000000000000000000000000000000000000000000080000000000020000000000000008000000000000000000000000000000000000002000000000000200000000000000000000000000000000000000000000000010000000000004000000000000000000001000000000000000000000000000000100000000000000000000000000000000000100000000000000000000000000000000000100000", + "blockHash": "0xf644de9f595b4e5d536127e07b220fb2e0e8345776629d51ff5d69cbe0624511", + "transactionHash": "0xc23938703c67a2d8159a0d161e22d712d6a8ee81590b19ba17bf900863f31e61", "logs": [ { - "transactionIndex": 45, - "blockNumber": 49649258, - "transactionHash": "0xcf3df608c1281faefc26d748439397600d37bfe3621dd727f0968b9b9b9f9b80", + "transactionIndex": 65, + "blockNumber": 63723228, + "transactionHash": "0xc23938703c67a2d8159a0d161e22d712d6a8ee81590b19ba17bf900863f31e61", "address": "0x0000000000000000000000000000000000001010", "topics": [ "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63", "0x0000000000000000000000000000000000000000000000000000000000001010", "0x000000000000000000000000a6e4ffa19b213abea258ae72e8e1a209b9e543e7", - "0x00000000000000000000000083d69448f88bf9c701c1b93f43e1f753d39b2632" + "0x0000000000000000000000001b0840519a581f3779d0a10b77593d6d3894a76a" ], - "data": "0x00000000000000000000000000000000000000000000000001779c94fe2dc000000000000000000000000000000000000000000000000000b839bbe06f6a624b0000000000000000000000000000000000000000000000b89a190d34a5b0242b000000000000000000000000000000000000000000000000b6c21f4b713ca24b0000000000000000000000000000000000000000000000b89b90a9c9a3dde42b", - "logIndex": 197, - "blockHash": "0xb244c634b14958cb2fedea7470e4ccdcadeac1f4c7e49b730421fae11c167d63" + "data": "0x00000000000000000000000000000000000000000000000000fb12998373a7cd0000000000000000000000000000000000000000000000003f855f19a7e8dc80000000000000000000000000000000000000000000005202ce026f2ae7a3a3080000000000000000000000000000000000000000000000003e8a4c80247534b3000000000000000000000000000000000000000000005202cefd81c46b174ad5", + "logIndex": 440, + "blockHash": "0xf644de9f595b4e5d536127e07b220fb2e0e8345776629d51ff5d69cbe0624511" } ], - "blockNumber": 49649258, - "cumulativeGasUsed": "9307532", + "blockNumber": 63723228, + "cumulativeGasUsed": "14645419", "status": 1, "byzantium": true }, "args": [ - 19 + 15 ], - "numDeployments": 4, - "solcInputHash": "4db3e1d3dd51dbe508dc0a6a04352df6", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_validatorsCount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"NotSupported\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"minAmountForStake\",\"type\":\"uint256\"}],\"name\":\"LogMinAmountForStake\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"NUMBER_OF_VALIDATORS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ONE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TOTAL_SUPPLY\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_0\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_1\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_10\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_11\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_12\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_13\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_14\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_15\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_16\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_17\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_18\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_2\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_3\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_4\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_5\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_6\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_7\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_8\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_9\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_ix\",\"type\":\"uint256\"}],\"name\":\"addresses\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validator\",\"type\":\"address\"}],\"name\":\"balances\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"create\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"exit\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBalances\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"allBalances\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumberOfValidators\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"receiveApproval\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"register\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"remove\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"setMinAmountForStake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"stake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"update\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_id\",\"type\":\"address\"}],\"name\":\"validators\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"location\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_validators\",\"type\":\"address[]\"}],\"name\":\"verifyValidators\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addresses(uint256)\":{\"details\":\"gets validator address for provided index\",\"params\":{\"_ix\":\"index in array of list of all validators wallets\"}},\"balanceOf(address)\":{\"details\":\"to follow ERC20 interface\"},\"exit()\":{\"details\":\"unstake and withdraw all tokens\"},\"getName()\":{\"details\":\"to follow Registrable interface\"},\"getNumberOfValidators()\":{\"returns\":{\"_0\":\"total number of registered validators (with and without balance)\"}},\"register()\":{\"details\":\"to follow Registrable interface\"},\"totalSupply()\":{\"details\":\"to follow ERC20 interface\"},\"unregister()\":{\"details\":\"to follow Registrable interface\"},\"validators(address)\":{\"params\":{\"_id\":\"address of validator\"},\"returns\":{\"id\":\"address of validator\",\"location\":\"URL of validator\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":\"StakingBankStaticProd\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":0},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBank.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IStakingBank is IERC20 {\\n /// @param id address of validator wallet\\n /// @param location URL of the validator API\\n struct Validator {\\n address id;\\n string location;\\n }\\n\\n event LogValidatorRegistered(address indexed id);\\n event LogValidatorUpdated(address indexed id);\\n event LogValidatorRemoved(address indexed id);\\n event LogMinAmountForStake(uint256 minAmountForStake);\\n\\n /// @dev setter for `minAmountForStake`\\n function setMinAmountForStake(uint256 _minAmountForStake) external;\\n\\n /// @dev allows to stake `token` by validators\\n /// Validator needs to approve StakingBank beforehand\\n /// @param _value amount of tokens to stake\\n function stake(uint256 _value) external;\\n\\n /// @dev notification about approval from `_from` address on UMB token\\n /// Staking bank will stake max approved amount from `_from` address\\n /// @param _from address which approved token spend for IStakingBank\\n function receiveApproval(address _from) external returns (bool success);\\n\\n /// @dev withdraws stake tokens\\n /// it throws, when balance will be less than required minimum for stake\\n /// to withdraw all use `exit`\\n function withdraw(uint256 _value) external returns (bool success);\\n\\n /// @dev unstake and withdraw all tokens\\n function exit() external returns (bool success);\\n\\n /// @dev creates (register) new validator\\n /// @param _id validator address\\n /// @param _location location URL of the validator API\\n function create(address _id, string calldata _location) external;\\n\\n /// @dev removes validator\\n /// @param _id validator wallet\\n function remove(address _id) external;\\n\\n /// @dev updates validator location\\n /// @param _id validator wallet\\n /// @param _location new validator URL\\n function update(address _id, string calldata _location) external;\\n\\n /// @return total number of registered validators (with and without balance)\\n function getNumberOfValidators() external view returns (uint256);\\n\\n /// @dev gets validator address for provided index\\n /// @param _ix index in array of list of all validators wallets\\n function addresses(uint256 _ix) external view returns (address);\\n\\n /// @param _id address of validator\\n /// @return id address of validator\\n /// @return location URL of validator\\n function validators(address _id) external view returns (address id, string memory location);\\n}\\n\",\"keccak256\":\"0x2c518aeab8b0b3a364fafaec559d3ff0dc6a119f8d203fa31ef7ad667ca0f7b9\",\"license\":\"MIT\"},\"contracts/interfaces/StakingBankStaticNotSupported.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./IStakingBank.sol\\\";\\n\\nabstract contract StakingBankStaticNotSupported is IStakingBank {\\n error NotSupported();\\n\\n function create(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function update(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function remove(address) external pure {\\n revert NotSupported();\\n }\\n\\n function transfer(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function transferFrom(address, address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function receiveApproval(address) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function allowance(address, address) external pure returns (uint256) {\\n revert NotSupported();\\n }\\n\\n function approve(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function stake(uint256) external pure {\\n revert NotSupported();\\n }\\n\\n function withdraw(uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function exit() external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function setMinAmountForStake(uint256) external pure {\\n revert NotSupported();\\n }\\n}\\n\",\"keccak256\":\"0xa899ad9000220b04bc3f63f762a9a6a76dcc09449427e7774a53f4ceda9c1cf8\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStatic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"../interfaces/StakingBankStaticNotSupported.sol\\\";\\n\\n/// @dev Because we are using PoA in UMB oracle, staked balance does not matter. What's matter is, if signer is\\n/// validator or not. In this case we can optimise `StakingBank` and make it static for better gas performance.\\nabstract contract StakingBankStatic is StakingBankStaticNotSupported {\\n uint256 public constant ONE = 1e18;\\n\\n uint256 public immutable NUMBER_OF_VALIDATORS; // solhint-disable-line var-name-mixedcase\\n uint256 public immutable TOTAL_SUPPLY; // solhint-disable-line var-name-mixedcase\\n\\n constructor(uint256 _validatorsCount) {\\n NUMBER_OF_VALIDATORS = _validatorsCount;\\n TOTAL_SUPPLY = _validatorsCount * ONE;\\n\\n _assertValidSetup(_validatorsCount);\\n }\\n\\n function balances(address _validator) external view returns (uint256) {\\n return _isValidator(_validator) ? ONE : 0;\\n }\\n\\n function verifyValidators(address[] calldata _validators) external view returns (bool) {\\n for (uint256 i; i < _validators.length;) {\\n if (!_isValidator(_validators[i])) return false;\\n unchecked { i++; }\\n }\\n\\n return true;\\n }\\n\\n function getNumberOfValidators() external view returns (uint256) {\\n return NUMBER_OF_VALIDATORS;\\n }\\n\\n function getAddresses() external view returns (address[] memory) {\\n return _addresses();\\n }\\n\\n function getBalances() external view returns (uint256[] memory allBalances) {\\n allBalances = new uint256[](NUMBER_OF_VALIDATORS);\\n\\n for (uint256 i; i < NUMBER_OF_VALIDATORS;) {\\n allBalances[i] = ONE;\\n\\n unchecked {\\n // we will not have enough data to overflow\\n i++;\\n }\\n }\\n }\\n\\n function addresses(uint256 _ix) external view returns (address) {\\n return _addresses()[_ix];\\n }\\n\\n function validators(address _id) external view virtual returns (address id, string memory location);\\n\\n /// @dev to follow ERC20 interface\\n function balanceOf(address _account) external view returns (uint256) {\\n return _isValidator(_account) ? ONE : 0;\\n }\\n\\n /// @dev to follow ERC20 interface\\n function totalSupply() external view returns (uint256) {\\n return TOTAL_SUPPLY;\\n }\\n\\n /// @dev to follow Registrable interface\\n function getName() external pure returns (bytes32) {\\n return \\\"StakingBank\\\";\\n }\\n\\n /// @dev to follow Registrable interface\\n function register() external pure {\\n // there are no requirements atm\\n }\\n\\n /// @dev to follow Registrable interface\\n function unregister() external pure {\\n // there are no requirements atm\\n }\\n\\n function _addresses() internal view virtual returns (address[] memory);\\n\\n function _isValidator(address _validator) internal view virtual returns (bool);\\n\\n function _assertValidSetup(uint256 _validatorsCount) internal view virtual{\\n address[] memory list = _addresses();\\n require(list.length == _validatorsCount);\\n\\n for (uint256 i; i < _validatorsCount;) {\\n require(_isValidator(list[i]));\\n\\n unchecked { i ++; }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfcc53ff98b0f1c42e1bc7345a1535fdc4e938ef40d323600ead94b2ece59a381\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./StakingBankStatic.sol\\\";\\n\\ncontract StakingBankStaticProd is StakingBankStatic {\\n address public constant VALIDATOR_0 = 0x977Ba523420110e230643B772Fe9cF955e11dA7B;\\n address public constant VALIDATOR_1 = 0xe2422b23e52bc13ebA04d7FbB9F332Deb43360fB;\\n\\n // external order is based on validators submits on AVAX for Apr 2023\\n address public constant VALIDATOR_2 = 0x57F404aD75e371c1A539589C1eFCA12e0C6980AD;\\n address public constant VALIDATOR_3 = 0xD56C6A4f64E0bD70260472d1DB6Cf5825858CB0d;\\n address public constant VALIDATOR_4 = 0x220230Eda8f50067Dd9e4729345dabCCe0C61542;\\n address public constant VALIDATOR_5 = 0x93FdcAB283b0BcAc48157590af482E1CFd6af6aC;\\n address public constant VALIDATOR_6 = 0xCd733E06B06083d52fC5867E8E3432aA5c103A38;\\n address public constant VALIDATOR_7 = 0x42e210b110c6aa49CdfA7ceF1444Aa4719653111;\\n address public constant VALIDATOR_8 = 0x501731c6a69803a53Ec6c3e12f293c247cE1092B;\\n address public constant VALIDATOR_9 = 0x8bF9661F1b247522C75DD0FE84355aD2EfF27144;\\n address public constant VALIDATOR_10 = 0x281754Ab58391A478B7aA4E7f39991CfB41118c4;\\n address public constant VALIDATOR_11 = 0xB9C63a350A04d8BD245d18928a26EE036352dDd8;\\n address public constant VALIDATOR_12 = 0x57A51D5BDcE188c2295fCA3b4687475a54E65A02;\\n address public constant VALIDATOR_13 = 0x777FbA3666fa7747476a34577FcCC404b263E09F;\\n address public constant VALIDATOR_14 = 0x2F85824B2B38F179E451988670935d315b5b9692;\\n address public constant VALIDATOR_15 = 0xA7241994267682de4dE7Ef62f52dc2C783d1784B;\\n address public constant VALIDATOR_16 = 0x6eEd457C20603EDAE50C3A112CAA1a9425321bD0;\\n address public constant VALIDATOR_17 = 0xC5a7650c2725a7B6A39f15cb9FbffC7af357AFeb;\\n address public constant VALIDATOR_18 = 0xFEd95453678920c1b7b3A81F033Ca02a27225556;\\n\\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\\n\\n // solhint-disable-next-line code-complexity\\n function validators(address _id) external pure override returns (address id, string memory location) {\\n if (_id == VALIDATOR_0) return (_id, \\\"https://validator.umb.network\\\");\\n if (_id == VALIDATOR_1) return (_id, \\\"https://validator2.umb.network\\\");\\n if (_id == VALIDATOR_2) return (_id, \\\"https://umbrella.artemahr.tech\\\");\\n if (_id == VALIDATOR_3) return (_id, \\\"https://umb.vtabsolutions.com:3030\\\");\\n if (_id == VALIDATOR_4) return (_id, \\\"https://umb.stakers.world\\\");\\n if (_id == VALIDATOR_5) return (_id, \\\"https://umbrella.crazywhale.es\\\");\\n if (_id == VALIDATOR_6) return (_id, \\\"https://umbrella-node.gateomega.com\\\");\\n if (_id == VALIDATOR_7) return (_id, \\\"https://umb.anorak.technology\\\");\\n if (_id == VALIDATOR_8) return (_id, \\\"https://umbrella.validator.infstones.io\\\");\\n if (_id == VALIDATOR_9) return (_id, \\\"https://umb.hashquark.io\\\");\\n if (_id == VALIDATOR_10) return (_id, \\\"http://umbrella.staking4all.org:3000\\\");\\n if (_id == VALIDATOR_11) return (_id, \\\"https://umbrella-api.validatrium.club\\\");\\n if (_id == VALIDATOR_12) return (_id, \\\"http://5.161.78.230:3000\\\");\\n if (_id == VALIDATOR_13) return (_id, \\\"https://umbnode.blockchainliverpool.com\\\");\\n if (_id == VALIDATOR_14) return (_id, \\\"https://umb-api.staking.rocks\\\");\\n if (_id == VALIDATOR_15) return (_id, \\\"https://rpc.urbanhq.net\\\");\\n if (_id == VALIDATOR_16) return (_id, \\\"https://umbrella-node.ankastake.com\\\");\\n if (_id == VALIDATOR_17) return (_id, \\\"https://umbrella.tchambrella.com\\\");\\n if (_id == VALIDATOR_18) return (_id, \\\"https://umbrella-node.cmt13.eu\\\");\\n\\n return (address(0), \\\"\\\");\\n }\\n\\n function _addresses() internal view override returns (address[] memory) {\\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\\n\\n list[0] = VALIDATOR_0;\\n list[1] = VALIDATOR_1;\\n list[2] = VALIDATOR_2;\\n list[3] = VALIDATOR_3;\\n list[4] = VALIDATOR_4;\\n list[5] = VALIDATOR_5;\\n list[6] = VALIDATOR_6;\\n list[7] = VALIDATOR_7;\\n list[8] = VALIDATOR_8;\\n list[9] = VALIDATOR_9;\\n list[10] = VALIDATOR_10;\\n list[11] = VALIDATOR_11;\\n list[12] = VALIDATOR_12;\\n list[13] = VALIDATOR_13;\\n list[14] = VALIDATOR_14;\\n list[15] = VALIDATOR_15;\\n list[16] = VALIDATOR_16;\\n list[17] = VALIDATOR_17;\\n list[18] = VALIDATOR_18;\\n\\n return list;\\n }\\n\\n function _isValidator(address _validator) internal pure override returns (bool) {\\n return (\\n _validator == VALIDATOR_0\\n || _validator == VALIDATOR_1\\n || _validator == VALIDATOR_2\\n || _validator == VALIDATOR_3\\n || _validator == VALIDATOR_4\\n || _validator == VALIDATOR_5\\n || _validator == VALIDATOR_6\\n || _validator == VALIDATOR_7\\n || _validator == VALIDATOR_8\\n || _validator == VALIDATOR_9\\n || _validator == VALIDATOR_10\\n || _validator == VALIDATOR_11\\n || _validator == VALIDATOR_12\\n || _validator == VALIDATOR_13\\n || _validator == VALIDATOR_14\\n || _validator == VALIDATOR_15\\n || _validator == VALIDATOR_16\\n || _validator == VALIDATOR_17\\n || _validator == VALIDATOR_18\\n );\\n }\\n}\\n\",\"keccak256\":\"0x1e80a063f381fdb75109238bd1e4db75af37b5aea8d8165293aee4bf84838c85\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60c06040523480156200001157600080fd5b5060405162003da238038062003da2833981810160405281019062000037919062000eaf565b808060808181525050670de0b6b3a76400008162000056919062000f10565b60a081815250506200006e816200007660201b60201c565b505062000fcf565b600062000088620000ef60201b60201c565b9050818151146200009857600080fd5b60005b82811015620000ea57620000d2828281518110620000be57620000bd62000f71565b5b6020026020010151620008dd60201b60201c565b620000dc57600080fd5b80806001019150506200009b565b505050565b6060600060805167ffffffffffffffff81111562000112576200011162000fa0565b5b604051908082528060200260200182016040528015620001415781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b8160008151811062000170576200016f62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110620001d657620001d562000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad816002815181106200023c576200023b62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110620002a257620002a162000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073220230eda8f50067dd9e4729345dabcce0c615428160048151811062000308576200030762000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac816005815181106200036e576200036d62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a3881600681518110620003d457620003d362000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa4719653111816007815181106200043a576200043962000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b81600881518110620004a0576200049f62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff271448160098151811062000506576200050562000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600a815181106200056c576200056b62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073b9c63a350a04d8bd245d18928a26ee036352ddd881600b81518110620005d257620005d162000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600c8151811062000638576200063762000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073777fba3666fa7747476a34577fccc404b263e09f81600d815181106200069e576200069d62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600e8151811062000704576200070362000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600f815181106200076a576200076962000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081601081518110620007d057620007cf62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb8160118151811062000836576200083562000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073fed95453678920c1b7b3a81f033ca02a27225556816012815181106200089c576200089b62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806200096d575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80620009b857507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a03575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a4e575073220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a9957507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ae4575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b2f57507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b7a575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000bc55750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000c10575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000c5b575073b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ca657507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000cf1575073777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000d3c5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000d87575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000dd25750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000e1d575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000e68575073fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b600080fd5b6000819050919050565b62000e898162000e74565b811462000e9557600080fd5b50565b60008151905062000ea98162000e7e565b92915050565b60006020828403121562000ec85762000ec762000e6f565b5b600062000ed88482850162000e98565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600062000f1d8262000e74565b915062000f2a8362000e74565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161562000f665762000f6562000ee1565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60805160a051612d8a62001018600039600081816109ac0152610c2e01526000818161081b0152818161088901528181610c5401528181610dbd0152611db40152612d8a6000f3fe608060405234801561001057600080fd5b50600436106102195760003560e01c8062113e081461021e578063015f7ed61461023c57806303a1e2241461025a578063095ea7b3146102785780630db18e37146102a857806317d7de7c146102d857806318160ddd146102f65780631aa3a008146103145780631d4f9ce01461031e57806323b872dd1461034e57806327e235e31461037e57806329092d0e146103ae5780632e1a7d4d146103ca578063398b056e146103fa578063411ff4971461041857806345f9f8251461043657806352b41e351461045457806354755335146104705780635dc4bfd31461048e57806361a3e37e146104ac57806369dc7ae4146104ca57806370a08231146104e8578063838e7c3a14610518578063902d55a5146105345780639031d9131461055257806390ff7e2e14610570578063952c4f181461058e578063989b6996146105ac5780639f0e9484146105ca578063a15ab08d146105e8578063a39fac1214610604578063a694fc3a14610622578063a9059cbb1461063e578063b2119eac1461066e578063b49b08421461068c578063c2ee3a08146106aa578063db731777146106c8578063dd62ed3e146106e6578063e214a5fc14610716578063e29349d614610734578063e2dc7a1a14610752578063e79a198f14610770578063e985e0081461077a578063e9fad8ee14610798578063edf26d9b146107b6578063fa52c7d8146107e6575b600080fd5b610226610817565b6040516102339190612645565b60405180910390f35b6102446108e8565b60405161025191906126a8565b60405180910390f35b610262610900565b60405161026f91906126a8565b60405180910390f35b610292600480360381019061028d9190612725565b610918565b60405161029f9190612780565b60405180910390f35b6102c260048036038101906102bd919061279b565b61094c565b6040516102cf9190612780565b60405180910390f35b6102e0610980565b6040516102ed91906127e1565b60405180910390f35b6102fe6109a8565b60405161030b919061280b565b60405180910390f35b61031c6109d0565b005b6103386004803603810190610333919061288b565b6109d2565b6040516103459190612780565b60405180910390f35b610368600480360381019061036391906128d8565b610a38565b6040516103759190612780565b60405180910390f35b6103986004803603810190610393919061279b565b610a6c565b6040516103a5919061280b565b60405180910390f35b6103c860048036038101906103c3919061279b565b610a93565b005b6103e460048036038101906103df919061292b565b610ac5565b6040516103f19190612780565b60405180910390f35b610402610af9565b60405161040f91906126a8565b60405180910390f35b610420610b11565b60405161042d91906126a8565b60405180910390f35b61043e610b29565b60405161044b91906126a8565b60405180910390f35b61046e6004803603810190610469919061292b565b610b41565b005b610478610b73565b60405161048591906126a8565b60405180910390f35b610496610b8b565b6040516104a391906126a8565b60405180910390f35b6104b4610ba3565b6040516104c191906126a8565b60405180910390f35b6104d2610bbb565b6040516104df91906126a8565b60405180910390f35b61050260048036038101906104fd919061279b565b610bd3565b60405161050f919061280b565b60405180910390f35b610532600480360381019061052d91906129ae565b610bfa565b005b61053c610c2c565b604051610549919061280b565b60405180910390f35b61055a610c50565b604051610567919061280b565b60405180910390f35b610578610c78565b60405161058591906126a8565b60405180910390f35b610596610c90565b6040516105a391906126a8565b60405180910390f35b6105b4610ca8565b6040516105c191906126a8565b60405180910390f35b6105d2610cc0565b6040516105df91906126a8565b60405180910390f35b61060260048036038101906105fd91906129ae565b610cd8565b005b61060c610d0a565b6040516106199190612acc565b60405180910390f35b61063c6004803603810190610637919061292b565b610d19565b005b61065860048036038101906106539190612725565b610d4b565b6040516106659190612780565b60405180910390f35b610676610d7f565b60405161068391906126a8565b60405180910390f35b610694610d97565b6040516106a191906126a8565b60405180910390f35b6106b2610daf565b6040516106bf919061280b565b60405180910390f35b6106d0610dbb565b6040516106dd919061280b565b60405180910390f35b61070060048036038101906106fb9190612aee565b610ddf565b60405161070d919061280b565b60405180910390f35b61071e610e13565b60405161072b91906126a8565b60405180910390f35b61073c610e2b565b60405161074991906126a8565b60405180910390f35b61075a610e43565b60405161076791906126a8565b60405180910390f35b610778610e5b565b005b610782610e5d565b60405161078f91906126a8565b60405180910390f35b6107a0610e75565b6040516107ad9190612780565b60405180910390f35b6107d060048036038101906107cb919061292b565b610ea9565b6040516107dd91906126a8565b60405180910390f35b61080060048036038101906107fb919061279b565b610ed4565b60405161080e929190612bc7565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff81111561085357610852612bf7565b5b6040519080825280602002602001820160405280156108815781602001602082028036833780820191505090505b50905060005b7f00000000000000000000000000000000000000000000000000000000000000008110156108e457670de0b6b3a76400008282815181106108cb576108ca612c26565b5b6020026020010181815250508080600101915050610887565b5090565b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b83839050811015610a2c57610a118484838181106109f7576109f6612c26565b5b9050602002016020810190610a0c919061279b565b61182e565b610a1f576000915050610a32565b80806001019150506109d6565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a778261182e565b610a82576000610a8c565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b732f85824b2b38f179e451988670935d315b5b969281565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b73fed95453678920c1b7b3a81f033ca02a2722555681565b73777fba3666fa7747476a34577fccc404b263e09f81565b6000610bde8261182e565b610be9576000610bf3565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b73220230eda8f50067dd9e4729345dabcce0c6154281565b73a7241994267682de4de7ef62f52dc2c783d1784b81565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610d14611dae565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73281754ab58391a478b7aa4e7f39991cfb41118c481565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b736eed457c20603edae50c3a112caa1a9425321bd081565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b565b73b9c63a350a04d8bd245d18928a26ee036352ddd881565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610eb3611dae565b8281518110610ec557610ec4612c26565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f5f57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611829565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fe657826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611829565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361106d57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611829565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110d75782604051806060016040528060228152602001612c796022913991509150611829565b73220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361115e57826040518060400160405280601981526020017f68747470733a2f2f756d622e7374616b6572732e776f726c640000000000000081525091509150611829565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111e557826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611829565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361124f5782604051806060016040528060238152602001612c566023913991509150611829565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112d657826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611829565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113405782604051806060016040528060278152602001612cbf6027913991509150611829565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113c757826040518060400160405280601881526020017f68747470733a2f2f756d622e68617368717561726b2e696f000000000000000081525091509150611829565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114315782604051806060016040528060248152602001612c9b6024913991509150611829565b73b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361149b5782604051806060016040528060258152602001612ce66025913991509150611829565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152257826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611829565b73777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361158c5782604051806060016040528060278152602001612d2e6027913991509150611829565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361161357826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611829565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361169a57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611829565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036117045782604051806060016040528060238152602001612d0b6023913991509150611829565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361178b57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611829565b73fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361181257826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612d6e6f64652e636d7431332e6575000081525091509150611829565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806118bd575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061190757507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611951575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061199b575073220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806119e557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a2f575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a7957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ac3575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b0d5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b57575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ba1575073b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611beb57507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c35575073777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c7f5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611cc9575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d135750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d5d575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611da7575073fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff811115611dec57611deb612bf7565b5b604051908082528060200260200182016040528015611e1a5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611e4657611e45612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611ea957611ea8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611f0c57611f0b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611f6f57611f6e612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073220230eda8f50067dd9e4729345dabcce0c6154281600481518110611fd257611fd1612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac8160058151811061203557612034612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a388160068151811061209857612097612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa4719653111816007815181106120fb576120fa612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b8160088151811061215e5761215d612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff27144816009815181106121c1576121c0612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600a8151811061222457612223612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073b9c63a350a04d8bd245d18928a26ee036352ddd881600b8151811061228757612286612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600c815181106122ea576122e9612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073777fba3666fa7747476a34577fccc404b263e09f81600d8151811061234d5761234c612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600e815181106123b0576123af612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600f8151811061241357612412612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd08160108151811061247657612475612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb816011815181106124d9576124d8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073fed95453678920c1b7b3a81f033ca02a272255568160128151811061253c5761253b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6125bc816125a9565b82525050565b60006125ce83836125b3565b60208301905092915050565b6000602082019050919050565b60006125f28261257d565b6125fc8185612588565b935061260783612599565b8060005b8381101561263857815161261f88826125c2565b975061262a836125da565b92505060018101905061260b565b5085935050505092915050565b6000602082019050818103600083015261265f81846125e7565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061269282612667565b9050919050565b6126a281612687565b82525050565b60006020820190506126bd6000830184612699565b92915050565b600080fd5b600080fd5b6126d681612687565b81146126e157600080fd5b50565b6000813590506126f3816126cd565b92915050565b612702816125a9565b811461270d57600080fd5b50565b60008135905061271f816126f9565b92915050565b6000806040838503121561273c5761273b6126c3565b5b600061274a858286016126e4565b925050602061275b85828601612710565b9150509250929050565b60008115159050919050565b61277a81612765565b82525050565b60006020820190506127956000830184612771565b92915050565b6000602082840312156127b1576127b06126c3565b5b60006127bf848285016126e4565b91505092915050565b6000819050919050565b6127db816127c8565b82525050565b60006020820190506127f660008301846127d2565b92915050565b612805816125a9565b82525050565b600060208201905061282060008301846127fc565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261284b5761284a612826565b5b8235905067ffffffffffffffff8111156128685761286761282b565b5b60208301915083602082028301111561288457612883612830565b5b9250929050565b600080602083850312156128a2576128a16126c3565b5b600083013567ffffffffffffffff8111156128c0576128bf6126c8565b5b6128cc85828601612835565b92509250509250929050565b6000806000606084860312156128f1576128f06126c3565b5b60006128ff868287016126e4565b9350506020612910868287016126e4565b925050604061292186828701612710565b9150509250925092565b600060208284031215612941576129406126c3565b5b600061294f84828501612710565b91505092915050565b60008083601f84011261296e5761296d612826565b5b8235905067ffffffffffffffff81111561298b5761298a61282b565b5b6020830191508360018202830111156129a7576129a6612830565b5b9250929050565b6000806000604084860312156129c7576129c66126c3565b5b60006129d5868287016126e4565b935050602084013567ffffffffffffffff8111156129f6576129f56126c8565b5b612a0286828701612958565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b612a4381612687565b82525050565b6000612a558383612a3a565b60208301905092915050565b6000602082019050919050565b6000612a7982612a0e565b612a838185612a19565b9350612a8e83612a2a565b8060005b83811015612abf578151612aa68882612a49565b9750612ab183612a61565b925050600181019050612a92565b5085935050505092915050565b60006020820190508181036000830152612ae68184612a6e565b905092915050565b60008060408385031215612b0557612b046126c3565b5b6000612b13858286016126e4565b9250506020612b24858286016126e4565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612b68578082015181840152602081019050612b4d565b83811115612b77576000848401525b50505050565b6000601f19601f8301169050919050565b6000612b9982612b2e565b612ba38185612b39565b9350612bb3818560208601612b4a565b612bbc81612b7d565b840191505092915050565b6000604082019050612bdc6000830185612699565b8181036020830152612bee8184612b8e565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6170692e76616c696461747269756d2e636c756268747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6d68747470733a2f2f756d626e6f64652e626c6f636b636861696e6c69766572706f6f6c2e636f6da26469706673582212209a1752a9ea487818b8a4d658f151da9487c0cc92638142159bacde7ec2d21f7564736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102195760003560e01c8062113e081461021e578063015f7ed61461023c57806303a1e2241461025a578063095ea7b3146102785780630db18e37146102a857806317d7de7c146102d857806318160ddd146102f65780631aa3a008146103145780631d4f9ce01461031e57806323b872dd1461034e57806327e235e31461037e57806329092d0e146103ae5780632e1a7d4d146103ca578063398b056e146103fa578063411ff4971461041857806345f9f8251461043657806352b41e351461045457806354755335146104705780635dc4bfd31461048e57806361a3e37e146104ac57806369dc7ae4146104ca57806370a08231146104e8578063838e7c3a14610518578063902d55a5146105345780639031d9131461055257806390ff7e2e14610570578063952c4f181461058e578063989b6996146105ac5780639f0e9484146105ca578063a15ab08d146105e8578063a39fac1214610604578063a694fc3a14610622578063a9059cbb1461063e578063b2119eac1461066e578063b49b08421461068c578063c2ee3a08146106aa578063db731777146106c8578063dd62ed3e146106e6578063e214a5fc14610716578063e29349d614610734578063e2dc7a1a14610752578063e79a198f14610770578063e985e0081461077a578063e9fad8ee14610798578063edf26d9b146107b6578063fa52c7d8146107e6575b600080fd5b610226610817565b6040516102339190612645565b60405180910390f35b6102446108e8565b60405161025191906126a8565b60405180910390f35b610262610900565b60405161026f91906126a8565b60405180910390f35b610292600480360381019061028d9190612725565b610918565b60405161029f9190612780565b60405180910390f35b6102c260048036038101906102bd919061279b565b61094c565b6040516102cf9190612780565b60405180910390f35b6102e0610980565b6040516102ed91906127e1565b60405180910390f35b6102fe6109a8565b60405161030b919061280b565b60405180910390f35b61031c6109d0565b005b6103386004803603810190610333919061288b565b6109d2565b6040516103459190612780565b60405180910390f35b610368600480360381019061036391906128d8565b610a38565b6040516103759190612780565b60405180910390f35b6103986004803603810190610393919061279b565b610a6c565b6040516103a5919061280b565b60405180910390f35b6103c860048036038101906103c3919061279b565b610a93565b005b6103e460048036038101906103df919061292b565b610ac5565b6040516103f19190612780565b60405180910390f35b610402610af9565b60405161040f91906126a8565b60405180910390f35b610420610b11565b60405161042d91906126a8565b60405180910390f35b61043e610b29565b60405161044b91906126a8565b60405180910390f35b61046e6004803603810190610469919061292b565b610b41565b005b610478610b73565b60405161048591906126a8565b60405180910390f35b610496610b8b565b6040516104a391906126a8565b60405180910390f35b6104b4610ba3565b6040516104c191906126a8565b60405180910390f35b6104d2610bbb565b6040516104df91906126a8565b60405180910390f35b61050260048036038101906104fd919061279b565b610bd3565b60405161050f919061280b565b60405180910390f35b610532600480360381019061052d91906129ae565b610bfa565b005b61053c610c2c565b604051610549919061280b565b60405180910390f35b61055a610c50565b604051610567919061280b565b60405180910390f35b610578610c78565b60405161058591906126a8565b60405180910390f35b610596610c90565b6040516105a391906126a8565b60405180910390f35b6105b4610ca8565b6040516105c191906126a8565b60405180910390f35b6105d2610cc0565b6040516105df91906126a8565b60405180910390f35b61060260048036038101906105fd91906129ae565b610cd8565b005b61060c610d0a565b6040516106199190612acc565b60405180910390f35b61063c6004803603810190610637919061292b565b610d19565b005b61065860048036038101906106539190612725565b610d4b565b6040516106659190612780565b60405180910390f35b610676610d7f565b60405161068391906126a8565b60405180910390f35b610694610d97565b6040516106a191906126a8565b60405180910390f35b6106b2610daf565b6040516106bf919061280b565b60405180910390f35b6106d0610dbb565b6040516106dd919061280b565b60405180910390f35b61070060048036038101906106fb9190612aee565b610ddf565b60405161070d919061280b565b60405180910390f35b61071e610e13565b60405161072b91906126a8565b60405180910390f35b61073c610e2b565b60405161074991906126a8565b60405180910390f35b61075a610e43565b60405161076791906126a8565b60405180910390f35b610778610e5b565b005b610782610e5d565b60405161078f91906126a8565b60405180910390f35b6107a0610e75565b6040516107ad9190612780565b60405180910390f35b6107d060048036038101906107cb919061292b565b610ea9565b6040516107dd91906126a8565b60405180910390f35b61080060048036038101906107fb919061279b565b610ed4565b60405161080e929190612bc7565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff81111561085357610852612bf7565b5b6040519080825280602002602001820160405280156108815781602001602082028036833780820191505090505b50905060005b7f00000000000000000000000000000000000000000000000000000000000000008110156108e457670de0b6b3a76400008282815181106108cb576108ca612c26565b5b6020026020010181815250508080600101915050610887565b5090565b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b83839050811015610a2c57610a118484838181106109f7576109f6612c26565b5b9050602002016020810190610a0c919061279b565b61182e565b610a1f576000915050610a32565b80806001019150506109d6565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a778261182e565b610a82576000610a8c565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b732f85824b2b38f179e451988670935d315b5b969281565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b73fed95453678920c1b7b3a81f033ca02a2722555681565b73777fba3666fa7747476a34577fccc404b263e09f81565b6000610bde8261182e565b610be9576000610bf3565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b73220230eda8f50067dd9e4729345dabcce0c6154281565b73a7241994267682de4de7ef62f52dc2c783d1784b81565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610d14611dae565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73281754ab58391a478b7aa4e7f39991cfb41118c481565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b736eed457c20603edae50c3a112caa1a9425321bd081565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b565b73b9c63a350a04d8bd245d18928a26ee036352ddd881565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610eb3611dae565b8281518110610ec557610ec4612c26565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f5f57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611829565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fe657826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611829565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361106d57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611829565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110d75782604051806060016040528060228152602001612c796022913991509150611829565b73220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361115e57826040518060400160405280601981526020017f68747470733a2f2f756d622e7374616b6572732e776f726c640000000000000081525091509150611829565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111e557826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611829565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361124f5782604051806060016040528060238152602001612c566023913991509150611829565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112d657826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611829565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113405782604051806060016040528060278152602001612cbf6027913991509150611829565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113c757826040518060400160405280601881526020017f68747470733a2f2f756d622e68617368717561726b2e696f000000000000000081525091509150611829565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114315782604051806060016040528060248152602001612c9b6024913991509150611829565b73b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361149b5782604051806060016040528060258152602001612ce66025913991509150611829565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152257826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611829565b73777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361158c5782604051806060016040528060278152602001612d2e6027913991509150611829565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361161357826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611829565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361169a57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611829565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036117045782604051806060016040528060238152602001612d0b6023913991509150611829565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361178b57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611829565b73fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361181257826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612d6e6f64652e636d7431332e6575000081525091509150611829565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806118bd575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061190757507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611951575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061199b575073220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806119e557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a2f575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a7957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ac3575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b0d5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b57575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ba1575073b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611beb57507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c35575073777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c7f5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611cc9575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d135750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d5d575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611da7575073fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff811115611dec57611deb612bf7565b5b604051908082528060200260200182016040528015611e1a5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611e4657611e45612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611ea957611ea8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611f0c57611f0b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611f6f57611f6e612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073220230eda8f50067dd9e4729345dabcce0c6154281600481518110611fd257611fd1612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac8160058151811061203557612034612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a388160068151811061209857612097612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa4719653111816007815181106120fb576120fa612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b8160088151811061215e5761215d612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff27144816009815181106121c1576121c0612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600a8151811061222457612223612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073b9c63a350a04d8bd245d18928a26ee036352ddd881600b8151811061228757612286612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600c815181106122ea576122e9612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073777fba3666fa7747476a34577fccc404b263e09f81600d8151811061234d5761234c612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600e815181106123b0576123af612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600f8151811061241357612412612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd08160108151811061247657612475612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb816011815181106124d9576124d8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073fed95453678920c1b7b3a81f033ca02a272255568160128151811061253c5761253b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6125bc816125a9565b82525050565b60006125ce83836125b3565b60208301905092915050565b6000602082019050919050565b60006125f28261257d565b6125fc8185612588565b935061260783612599565b8060005b8381101561263857815161261f88826125c2565b975061262a836125da565b92505060018101905061260b565b5085935050505092915050565b6000602082019050818103600083015261265f81846125e7565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061269282612667565b9050919050565b6126a281612687565b82525050565b60006020820190506126bd6000830184612699565b92915050565b600080fd5b600080fd5b6126d681612687565b81146126e157600080fd5b50565b6000813590506126f3816126cd565b92915050565b612702816125a9565b811461270d57600080fd5b50565b60008135905061271f816126f9565b92915050565b6000806040838503121561273c5761273b6126c3565b5b600061274a858286016126e4565b925050602061275b85828601612710565b9150509250929050565b60008115159050919050565b61277a81612765565b82525050565b60006020820190506127956000830184612771565b92915050565b6000602082840312156127b1576127b06126c3565b5b60006127bf848285016126e4565b91505092915050565b6000819050919050565b6127db816127c8565b82525050565b60006020820190506127f660008301846127d2565b92915050565b612805816125a9565b82525050565b600060208201905061282060008301846127fc565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261284b5761284a612826565b5b8235905067ffffffffffffffff8111156128685761286761282b565b5b60208301915083602082028301111561288457612883612830565b5b9250929050565b600080602083850312156128a2576128a16126c3565b5b600083013567ffffffffffffffff8111156128c0576128bf6126c8565b5b6128cc85828601612835565b92509250509250929050565b6000806000606084860312156128f1576128f06126c3565b5b60006128ff868287016126e4565b9350506020612910868287016126e4565b925050604061292186828701612710565b9150509250925092565b600060208284031215612941576129406126c3565b5b600061294f84828501612710565b91505092915050565b60008083601f84011261296e5761296d612826565b5b8235905067ffffffffffffffff81111561298b5761298a61282b565b5b6020830191508360018202830111156129a7576129a6612830565b5b9250929050565b6000806000604084860312156129c7576129c66126c3565b5b60006129d5868287016126e4565b935050602084013567ffffffffffffffff8111156129f6576129f56126c8565b5b612a0286828701612958565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b612a4381612687565b82525050565b6000612a558383612a3a565b60208301905092915050565b6000602082019050919050565b6000612a7982612a0e565b612a838185612a19565b9350612a8e83612a2a565b8060005b83811015612abf578151612aa68882612a49565b9750612ab183612a61565b925050600181019050612a92565b5085935050505092915050565b60006020820190508181036000830152612ae68184612a6e565b905092915050565b60008060408385031215612b0557612b046126c3565b5b6000612b13858286016126e4565b9250506020612b24858286016126e4565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612b68578082015181840152602081019050612b4d565b83811115612b77576000848401525b50505050565b6000601f19601f8301169050919050565b6000612b9982612b2e565b612ba38185612b39565b9350612bb3818560208601612b4a565b612bbc81612b7d565b840191505092915050565b6000604082019050612bdc6000830185612699565b8181036020830152612bee8184612b8e565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6170692e76616c696461747269756d2e636c756268747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6d68747470733a2f2f756d626e6f64652e626c6f636b636861696e6c69766572706f6f6c2e636f6da26469706673582212209a1752a9ea487818b8a4d658f151da9487c0cc92638142159bacde7ec2d21f7564736f6c634300080d0033", + "numDeployments": 5, + "solcInputHash": "dc68422c0ad35a4fe46d461b096b9383", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_validatorsCount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"NotSupported\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"minAmountForStake\",\"type\":\"uint256\"}],\"name\":\"LogMinAmountForStake\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"NUMBER_OF_VALIDATORS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ONE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TOTAL_SUPPLY\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_0\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_1\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_10\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_11\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_12\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_13\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_14\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_2\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_3\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_4\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_5\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_6\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_7\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_8\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_9\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_ix\",\"type\":\"uint256\"}],\"name\":\"addresses\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validator\",\"type\":\"address\"}],\"name\":\"balances\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"create\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"exit\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBalances\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"allBalances\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumberOfValidators\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"receiveApproval\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"register\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"remove\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"setMinAmountForStake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"stake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"update\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_id\",\"type\":\"address\"}],\"name\":\"validators\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"location\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_validators\",\"type\":\"address[]\"}],\"name\":\"verifyValidators\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addresses(uint256)\":{\"details\":\"gets validator address for provided index\",\"params\":{\"_ix\":\"index in array of list of all validators wallets\"}},\"balanceOf(address)\":{\"details\":\"to follow ERC20 interface\"},\"exit()\":{\"details\":\"unstake and withdraw all tokens\"},\"getName()\":{\"details\":\"to follow Registrable interface\"},\"getNumberOfValidators()\":{\"returns\":{\"_0\":\"total number of registered validators (with and without balance)\"}},\"register()\":{\"details\":\"to follow Registrable interface\"},\"totalSupply()\":{\"details\":\"to follow ERC20 interface\"},\"unregister()\":{\"details\":\"to follow Registrable interface\"},\"validators(address)\":{\"params\":{\"_id\":\"address of validator\"},\"returns\":{\"id\":\"address of validator\",\"location\":\"URL of validator\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":\"StakingBankStaticProd\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":0},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBank.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IStakingBank is IERC20 {\\n /// @param id address of validator wallet\\n /// @param location URL of the validator API\\n struct Validator {\\n address id;\\n string location;\\n }\\n\\n event LogValidatorRegistered(address indexed id);\\n event LogValidatorUpdated(address indexed id);\\n event LogValidatorRemoved(address indexed id);\\n event LogMinAmountForStake(uint256 minAmountForStake);\\n\\n /// @dev setter for `minAmountForStake`\\n function setMinAmountForStake(uint256 _minAmountForStake) external;\\n\\n /// @dev allows to stake `token` by validators\\n /// Validator needs to approve StakingBank beforehand\\n /// @param _value amount of tokens to stake\\n function stake(uint256 _value) external;\\n\\n /// @dev notification about approval from `_from` address on UMB token\\n /// Staking bank will stake max approved amount from `_from` address\\n /// @param _from address which approved token spend for IStakingBank\\n function receiveApproval(address _from) external returns (bool success);\\n\\n /// @dev withdraws stake tokens\\n /// it throws, when balance will be less than required minimum for stake\\n /// to withdraw all use `exit`\\n function withdraw(uint256 _value) external returns (bool success);\\n\\n /// @dev unstake and withdraw all tokens\\n function exit() external returns (bool success);\\n\\n /// @dev creates (register) new validator\\n /// @param _id validator address\\n /// @param _location location URL of the validator API\\n function create(address _id, string calldata _location) external;\\n\\n /// @dev removes validator\\n /// @param _id validator wallet\\n function remove(address _id) external;\\n\\n /// @dev updates validator location\\n /// @param _id validator wallet\\n /// @param _location new validator URL\\n function update(address _id, string calldata _location) external;\\n\\n /// @return total number of registered validators (with and without balance)\\n function getNumberOfValidators() external view returns (uint256);\\n\\n /// @dev gets validator address for provided index\\n /// @param _ix index in array of list of all validators wallets\\n function addresses(uint256 _ix) external view returns (address);\\n\\n /// @param _id address of validator\\n /// @return id address of validator\\n /// @return location URL of validator\\n function validators(address _id) external view returns (address id, string memory location);\\n}\\n\",\"keccak256\":\"0x2c518aeab8b0b3a364fafaec559d3ff0dc6a119f8d203fa31ef7ad667ca0f7b9\",\"license\":\"MIT\"},\"contracts/interfaces/StakingBankStaticNotSupported.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./IStakingBank.sol\\\";\\n\\nabstract contract StakingBankStaticNotSupported is IStakingBank {\\n error NotSupported();\\n\\n function create(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function update(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function remove(address) external pure {\\n revert NotSupported();\\n }\\n\\n function transfer(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function transferFrom(address, address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function receiveApproval(address) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function allowance(address, address) external pure returns (uint256) {\\n revert NotSupported();\\n }\\n\\n function approve(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function stake(uint256) external pure {\\n revert NotSupported();\\n }\\n\\n function withdraw(uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function exit() external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function setMinAmountForStake(uint256) external pure {\\n revert NotSupported();\\n }\\n}\\n\",\"keccak256\":\"0xa899ad9000220b04bc3f63f762a9a6a76dcc09449427e7774a53f4ceda9c1cf8\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStatic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"../interfaces/StakingBankStaticNotSupported.sol\\\";\\n\\n/// @dev Because we are using PoA in UMB oracle, staked balance does not matter. What's matter is, if signer is\\n/// validator or not. In this case we can optimise `StakingBank` and make it static for better gas performance.\\nabstract contract StakingBankStatic is StakingBankStaticNotSupported {\\n uint256 public constant ONE = 1e18;\\n\\n uint256 public immutable NUMBER_OF_VALIDATORS; // solhint-disable-line var-name-mixedcase\\n uint256 public immutable TOTAL_SUPPLY; // solhint-disable-line var-name-mixedcase\\n\\n constructor(uint256 _validatorsCount) {\\n NUMBER_OF_VALIDATORS = _validatorsCount;\\n TOTAL_SUPPLY = _validatorsCount * ONE;\\n\\n _assertValidSetup(_validatorsCount);\\n }\\n\\n function balances(address _validator) external view returns (uint256) {\\n return _isValidator(_validator) ? ONE : 0;\\n }\\n\\n function verifyValidators(address[] calldata _validators) external view returns (bool) {\\n for (uint256 i; i < _validators.length;) {\\n if (!_isValidator(_validators[i])) return false;\\n unchecked { i++; }\\n }\\n\\n return true;\\n }\\n\\n function getNumberOfValidators() external view returns (uint256) {\\n return NUMBER_OF_VALIDATORS;\\n }\\n\\n function getAddresses() external view returns (address[] memory) {\\n return _addresses();\\n }\\n\\n function getBalances() external view returns (uint256[] memory allBalances) {\\n allBalances = new uint256[](NUMBER_OF_VALIDATORS);\\n\\n for (uint256 i; i < NUMBER_OF_VALIDATORS;) {\\n allBalances[i] = ONE;\\n\\n unchecked {\\n // we will not have enough data to overflow\\n i++;\\n }\\n }\\n }\\n\\n function addresses(uint256 _ix) external view returns (address) {\\n return _addresses()[_ix];\\n }\\n\\n function validators(address _id) external view virtual returns (address id, string memory location);\\n\\n /// @dev to follow ERC20 interface\\n function balanceOf(address _account) external view returns (uint256) {\\n return _isValidator(_account) ? ONE : 0;\\n }\\n\\n /// @dev to follow ERC20 interface\\n function totalSupply() external view returns (uint256) {\\n return TOTAL_SUPPLY;\\n }\\n\\n /// @dev to follow Registrable interface\\n function getName() external pure returns (bytes32) {\\n return \\\"StakingBank\\\";\\n }\\n\\n /// @dev to follow Registrable interface\\n function register() external pure {\\n // there are no requirements atm\\n }\\n\\n /// @dev to follow Registrable interface\\n function unregister() external pure {\\n // there are no requirements atm\\n }\\n\\n function _addresses() internal view virtual returns (address[] memory);\\n\\n function _isValidator(address _validator) internal view virtual returns (bool);\\n\\n function _assertValidSetup(uint256 _validatorsCount) internal view virtual{\\n address[] memory list = _addresses();\\n require(list.length == _validatorsCount);\\n\\n for (uint256 i; i < _validatorsCount;) {\\n require(_isValidator(list[i]));\\n\\n unchecked { i ++; }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfcc53ff98b0f1c42e1bc7345a1535fdc4e938ef40d323600ead94b2ece59a381\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./StakingBankStatic.sol\\\";\\n\\ncontract StakingBankStaticProd is StakingBankStatic {\\n address public constant VALIDATOR_0 = 0x977Ba523420110e230643B772Fe9cF955e11dA7B;\\n address public constant VALIDATOR_1 = 0xe2422b23e52bc13ebA04d7FbB9F332Deb43360fB;\\n\\n // external order is based on validators submits on AVAX for Apr 2023\\n address public constant VALIDATOR_2 = 0x57F404aD75e371c1A539589C1eFCA12e0C6980AD;\\n address public constant VALIDATOR_3 = 0xD56C6A4f64E0bD70260472d1DB6Cf5825858CB0d;\\n address public constant VALIDATOR_4 = 0x93FdcAB283b0BcAc48157590af482E1CFd6af6aC;\\n address public constant VALIDATOR_5 = 0xCd733E06B06083d52fC5867E8E3432aA5c103A38;\\n address public constant VALIDATOR_6 = 0x42e210b110c6aa49CdfA7ceF1444Aa4719653111;\\n address public constant VALIDATOR_7 = 0x501731c6a69803a53Ec6c3e12f293c247cE1092B;\\n address public constant VALIDATOR_8 = 0x8bF9661F1b247522C75DD0FE84355aD2EfF27144;\\n address public constant VALIDATOR_9 = 0x281754Ab58391A478B7aA4E7f39991CfB41118c4;\\n address public constant VALIDATOR_10 = 0x57A51D5BDcE188c2295fCA3b4687475a54E65A02;\\n address public constant VALIDATOR_11 = 0x2F85824B2B38F179E451988670935d315b5b9692;\\n address public constant VALIDATOR_12 = 0xA7241994267682de4dE7Ef62f52dc2C783d1784B;\\n address public constant VALIDATOR_13 = 0x6eEd457C20603EDAE50C3A112CAA1a9425321bD0;\\n address public constant VALIDATOR_14 = 0xC5a7650c2725a7B6A39f15cb9FbffC7af357AFeb;\\n\\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\\n\\n // solhint-disable-next-line code-complexity\\n function validators(address _id) external pure override returns (address id, string memory location) {\\n if (_id == VALIDATOR_0) return (_id, \\\"https://validator.umb.network\\\");\\n if (_id == VALIDATOR_1) return (_id, \\\"https://validator2.umb.network\\\");\\n if (_id == VALIDATOR_2) return (_id, \\\"https://umbrella.artemahr.tech\\\");\\n if (_id == VALIDATOR_3) return (_id, \\\"https://umb.vtabsolutions.com:3030\\\");\\n if (_id == VALIDATOR_4) return (_id, \\\"https://umbrella.crazywhale.es\\\");\\n if (_id == VALIDATOR_5) return (_id, \\\"https://umbrella-node.gateomega.com\\\");\\n if (_id == VALIDATOR_6) return (_id, \\\"https://umb.anorak.technology\\\");\\n if (_id == VALIDATOR_7) return (_id, \\\"https://umbrella.validator.infstones.io\\\");\\n if (_id == VALIDATOR_8) return (_id, \\\"https://umb.hashkey.cloud\\\");\\n if (_id == VALIDATOR_9) return (_id, \\\"http://umbrella.staking4all.org:3000\\\");\\n if (_id == VALIDATOR_10) return (_id, \\\"http://5.161.78.230:3000\\\");\\n if (_id == VALIDATOR_11) return (_id, \\\"https://umb-api.staking.rocks\\\");\\n if (_id == VALIDATOR_12) return (_id, \\\"https://rpc.urbanhq.net\\\");\\n if (_id == VALIDATOR_13) return (_id, \\\"https://umbrella-node.ankastake.com\\\");\\n if (_id == VALIDATOR_14) return (_id, \\\"https://umbrella.tchambrella.com\\\");\\n\\n return (address(0), \\\"\\\");\\n }\\n\\n function _addresses() internal view override returns (address[] memory) {\\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\\n\\n list[0] = VALIDATOR_0;\\n list[1] = VALIDATOR_1;\\n list[2] = VALIDATOR_2;\\n list[3] = VALIDATOR_3;\\n list[4] = VALIDATOR_4;\\n list[5] = VALIDATOR_5;\\n list[6] = VALIDATOR_6;\\n list[7] = VALIDATOR_7;\\n list[8] = VALIDATOR_8;\\n list[9] = VALIDATOR_9;\\n list[10] = VALIDATOR_10;\\n list[11] = VALIDATOR_11;\\n list[12] = VALIDATOR_12;\\n list[13] = VALIDATOR_13;\\n list[14] = VALIDATOR_14;\\n\\n return list;\\n }\\n\\n function _isValidator(address _validator) internal pure override returns (bool) {\\n return (\\n _validator == VALIDATOR_0\\n || _validator == VALIDATOR_1\\n || _validator == VALIDATOR_2\\n || _validator == VALIDATOR_3\\n || _validator == VALIDATOR_4\\n || _validator == VALIDATOR_5\\n || _validator == VALIDATOR_6\\n || _validator == VALIDATOR_7\\n || _validator == VALIDATOR_8\\n || _validator == VALIDATOR_9\\n || _validator == VALIDATOR_10\\n || _validator == VALIDATOR_11\\n || _validator == VALIDATOR_12\\n || _validator == VALIDATOR_13\\n || _validator == VALIDATOR_14\\n );\\n }\\n}\\n\",\"keccak256\":\"0xcf8016c7d7325800fb6ac9f7afd34804b738daded6239139b23f894855a4f98b\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c06040523480156200001157600080fd5b50604051620034f8380380620034f8833981810160405281019062000037919062000beb565b808060808181525050670de0b6b3a76400008162000056919062000c4c565b60a081815250506200006e816200007660201b60201c565b505062000d0b565b600062000088620000ef60201b60201c565b9050818151146200009857600080fd5b60005b82811015620000ea57620000d2828281518110620000be57620000bd62000cad565b5b60200260200101516200074560201b60201c565b620000dc57600080fd5b80806001019150506200009b565b505050565b6060600060805167ffffffffffffffff81111562000112576200011162000cdc565b5b604051908082528060200260200182016040528015620001415781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b8160008151811062000170576200016f62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110620001d657620001d562000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad816002815181106200023c576200023b62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110620002a257620002a162000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac8160048151811062000308576200030762000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a38816005815181106200036e576200036d62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa471965311181600681518110620003d457620003d362000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b816007815181106200043a576200043962000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff2714481600881518110620004a0576200049f62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c48160098151811062000506576200050562000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600a815181106200056c576200056b62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600b81518110620005d257620005d162000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600c8151811062000638576200063762000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081600d815181106200069e576200069d62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81600e8151811062000704576200070362000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480620007d5575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806200082057507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806200086b575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80620008b657507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000901575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806200094c57507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000997575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80620009e25750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a2d575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a7857507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ac35750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b0e575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b595750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ba4575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b600080fd5b6000819050919050565b62000bc58162000bb0565b811462000bd157600080fd5b50565b60008151905062000be58162000bba565b92915050565b60006020828403121562000c045762000c0362000bab565b5b600062000c148482850162000bd4565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600062000c598262000bb0565b915062000c668362000bb0565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161562000ca25762000ca162000c1d565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60805160a0516127a462000d54600039600081816109080152610b72015260008181610777015281816107e501528181610b9801528181610ce901526119a601526127a46000f3fe608060405234801561001057600080fd5b50600436106101ed5760003560e01c8062113e08146101f2578063015f7ed61461021057806303a1e2241461022e578063095ea7b31461024c5780630db18e371461027c57806317d7de7c146102ac57806318160ddd146102ca5780631aa3a008146102e85780631d4f9ce0146102f257806323b872dd1461032257806327e235e31461035257806329092d0e146103825780632e1a7d4d1461039e578063398b056e146103ce578063411ff497146103ec57806345f9f8251461040a57806352b41e351461042857806354755335146104445780635dc4bfd31461046257806369dc7ae41461048057806370a082311461049e578063838e7c3a146104ce578063902d55a5146104ea5780639031d9131461050857806390ff7e2e14610526578063989b6996146105445780639f0e948414610562578063a15ab08d14610580578063a39fac121461059c578063a694fc3a146105ba578063a9059cbb146105d6578063b2119eac14610606578063b49b084214610624578063c2ee3a0814610642578063db73177714610660578063dd62ed3e1461067e578063e2dc7a1a146106ae578063e79a198f146106cc578063e985e008146106d6578063e9fad8ee146106f4578063edf26d9b14610712578063fa52c7d814610742575b600080fd5b6101fa610773565b60405161020791906120ab565b60405180910390f35b610218610844565b604051610225919061210e565b60405180910390f35b61023661085c565b604051610243919061210e565b60405180910390f35b6102666004803603810190610261919061218b565b610874565b60405161027391906121e6565b60405180910390f35b61029660048036038101906102919190612201565b6108a8565b6040516102a391906121e6565b60405180910390f35b6102b46108dc565b6040516102c19190612247565b60405180910390f35b6102d2610904565b6040516102df9190612271565b60405180910390f35b6102f061092c565b005b61030c600480360381019061030791906122f1565b61092e565b60405161031991906121e6565b60405180910390f35b61033c6004803603810190610337919061233e565b610994565b60405161034991906121e6565b60405180910390f35b61036c60048036038101906103679190612201565b6109c8565b6040516103799190612271565b60405180910390f35b61039c60048036038101906103979190612201565b6109ef565b005b6103b860048036038101906103b39190612391565b610a21565b6040516103c591906121e6565b60405180910390f35b6103d6610a55565b6040516103e3919061210e565b60405180910390f35b6103f4610a6d565b604051610401919061210e565b60405180910390f35b610412610a85565b60405161041f919061210e565b60405180910390f35b610442600480360381019061043d9190612391565b610a9d565b005b61044c610acf565b604051610459919061210e565b60405180910390f35b61046a610ae7565b604051610477919061210e565b60405180910390f35b610488610aff565b604051610495919061210e565b60405180910390f35b6104b860048036038101906104b39190612201565b610b17565b6040516104c59190612271565b60405180910390f35b6104e860048036038101906104e39190612414565b610b3e565b005b6104f2610b70565b6040516104ff9190612271565b60405180910390f35b610510610b94565b60405161051d9190612271565b60405180910390f35b61052e610bbc565b60405161053b919061210e565b60405180910390f35b61054c610bd4565b604051610559919061210e565b60405180910390f35b61056a610bec565b604051610577919061210e565b60405180910390f35b61059a60048036038101906105959190612414565b610c04565b005b6105a4610c36565b6040516105b19190612532565b60405180910390f35b6105d460048036038101906105cf9190612391565b610c45565b005b6105f060048036038101906105eb919061218b565b610c77565b6040516105fd91906121e6565b60405180910390f35b61060e610cab565b60405161061b919061210e565b60405180910390f35b61062c610cc3565b604051610639919061210e565b60405180910390f35b61064a610cdb565b6040516106579190612271565b60405180910390f35b610668610ce7565b6040516106759190612271565b60405180910390f35b61069860048036038101906106939190612554565b610d0b565b6040516106a59190612271565b60405180910390f35b6106b6610d3f565b6040516106c3919061210e565b60405180910390f35b6106d4610d57565b005b6106de610d59565b6040516106eb919061210e565b60405180910390f35b6106fc610d71565b60405161070991906121e6565b60405180910390f35b61072c60048036038101906107279190612391565b610da5565b604051610739919061210e565b60405180910390f35b61075c60048036038101906107579190612201565b610dd0565b60405161076a92919061262d565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156107af576107ae61265d565b5b6040519080825280602002602001820160405280156107dd5781602001602082028036833780820191505090505b50905060005b7f000000000000000000000000000000000000000000000000000000000000000081101561084057670de0b6b3a76400008282815181106108275761082661268c565b5b60200260200101818152505080806001019150506107e3565b5090565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b838390508110156109885761096d8484838181106109535761095261268c565b5b90506020020160208101906109689190612201565b611548565b61097b57600091505061098e565b8080600101915050610932565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006109d382611548565b6109de5760006109e8565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73a7241994267682de4de7ef62f52dc2c783d1784b81565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b736eed457c20603edae50c3a112caa1a9425321bd081565b6000610b2282611548565b610b2d576000610b37565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73281754ab58391a478b7aa4e7f39991cfb41118c481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610c406119a0565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b565b732f85824b2b38f179e451988670935d315b5b969281565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610daf6119a0565b8281518110610dc157610dc061268c565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e5b57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611543565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610ee257826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611543565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f6957826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611543565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fd357826040518060600160405280602281526020016126df6022913991509150611543565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361105a57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611543565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110c457826040518060600160405280602381526020016126bc6023913991509150611543565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361114b57826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611543565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111b557826040518060600160405280602781526020016127256027913991509150611543565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361123c57826040518060400160405280601981526020017f68747470733a2f2f756d622e686173686b65792e636c6f75640000000000000081525091509150611543565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112a657826040518060600160405280602481526020016127016024913991509150611543565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361132d57826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611543565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113b457826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611543565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361143b57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611543565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114a5578260405180606001604052806023815260200161274c6023913991509150611543565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152c57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611543565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806115d7575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061162157507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061166b575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116b557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116ff575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061174957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611793575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806117dd5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611827575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061187157507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806118bb5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611905575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061194f5750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611999575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156119de576119dd61265d565b5b604051908082528060200260200182016040528015611a0c5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611a3857611a3761268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611a9b57611a9a61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611afe57611afd61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611b6157611b6061268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac81600481518110611bc457611bc361268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a3881600581518110611c2757611c2661268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa471965311181600681518110611c8a57611c8961268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b81600781518110611ced57611cec61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff2714481600881518110611d5057611d4f61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600981518110611db357611db261268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600a81518110611e1657611e1561268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600b81518110611e7957611e7861268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600c81518110611edc57611edb61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081600d81518110611f3f57611f3e61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81600e81518110611fa257611fa161268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6120228161200f565b82525050565b60006120348383612019565b60208301905092915050565b6000602082019050919050565b600061205882611fe3565b6120628185611fee565b935061206d83611fff565b8060005b8381101561209e5781516120858882612028565b975061209083612040565b925050600181019050612071565b5085935050505092915050565b600060208201905081810360008301526120c5818461204d565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006120f8826120cd565b9050919050565b612108816120ed565b82525050565b600060208201905061212360008301846120ff565b92915050565b600080fd5b600080fd5b61213c816120ed565b811461214757600080fd5b50565b60008135905061215981612133565b92915050565b6121688161200f565b811461217357600080fd5b50565b6000813590506121858161215f565b92915050565b600080604083850312156121a2576121a1612129565b5b60006121b08582860161214a565b92505060206121c185828601612176565b9150509250929050565b60008115159050919050565b6121e0816121cb565b82525050565b60006020820190506121fb60008301846121d7565b92915050565b60006020828403121561221757612216612129565b5b60006122258482850161214a565b91505092915050565b6000819050919050565b6122418161222e565b82525050565b600060208201905061225c6000830184612238565b92915050565b61226b8161200f565b82525050565b60006020820190506122866000830184612262565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126122b1576122b061228c565b5b8235905067ffffffffffffffff8111156122ce576122cd612291565b5b6020830191508360208202830111156122ea576122e9612296565b5b9250929050565b6000806020838503121561230857612307612129565b5b600083013567ffffffffffffffff8111156123265761232561212e565b5b6123328582860161229b565b92509250509250929050565b60008060006060848603121561235757612356612129565b5b60006123658682870161214a565b93505060206123768682870161214a565b925050604061238786828701612176565b9150509250925092565b6000602082840312156123a7576123a6612129565b5b60006123b584828501612176565b91505092915050565b60008083601f8401126123d4576123d361228c565b5b8235905067ffffffffffffffff8111156123f1576123f0612291565b5b60208301915083600182028301111561240d5761240c612296565b5b9250929050565b60008060006040848603121561242d5761242c612129565b5b600061243b8682870161214a565b935050602084013567ffffffffffffffff81111561245c5761245b61212e565b5b612468868287016123be565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6124a9816120ed565b82525050565b60006124bb83836124a0565b60208301905092915050565b6000602082019050919050565b60006124df82612474565b6124e9818561247f565b93506124f483612490565b8060005b8381101561252557815161250c88826124af565b9750612517836124c7565b9250506001810190506124f8565b5085935050505092915050565b6000602082019050818103600083015261254c81846124d4565b905092915050565b6000806040838503121561256b5761256a612129565b5b60006125798582860161214a565b925050602061258a8582860161214a565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156125ce5780820151818401526020810190506125b3565b838111156125dd576000848401525b50505050565b6000601f19601f8301169050919050565b60006125ff82612594565b612609818561259f565b93506126198185602086016125b0565b612622816125e3565b840191505092915050565b600060408201905061264260008301856120ff565b818103602083015261265481846125f4565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6da2646970667358221220b875faa4ff94a6ed380db1c82cfc4fcfdce28d00988b3f85c113e0332affbaa264736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101ed5760003560e01c8062113e08146101f2578063015f7ed61461021057806303a1e2241461022e578063095ea7b31461024c5780630db18e371461027c57806317d7de7c146102ac57806318160ddd146102ca5780631aa3a008146102e85780631d4f9ce0146102f257806323b872dd1461032257806327e235e31461035257806329092d0e146103825780632e1a7d4d1461039e578063398b056e146103ce578063411ff497146103ec57806345f9f8251461040a57806352b41e351461042857806354755335146104445780635dc4bfd31461046257806369dc7ae41461048057806370a082311461049e578063838e7c3a146104ce578063902d55a5146104ea5780639031d9131461050857806390ff7e2e14610526578063989b6996146105445780639f0e948414610562578063a15ab08d14610580578063a39fac121461059c578063a694fc3a146105ba578063a9059cbb146105d6578063b2119eac14610606578063b49b084214610624578063c2ee3a0814610642578063db73177714610660578063dd62ed3e1461067e578063e2dc7a1a146106ae578063e79a198f146106cc578063e985e008146106d6578063e9fad8ee146106f4578063edf26d9b14610712578063fa52c7d814610742575b600080fd5b6101fa610773565b60405161020791906120ab565b60405180910390f35b610218610844565b604051610225919061210e565b60405180910390f35b61023661085c565b604051610243919061210e565b60405180910390f35b6102666004803603810190610261919061218b565b610874565b60405161027391906121e6565b60405180910390f35b61029660048036038101906102919190612201565b6108a8565b6040516102a391906121e6565b60405180910390f35b6102b46108dc565b6040516102c19190612247565b60405180910390f35b6102d2610904565b6040516102df9190612271565b60405180910390f35b6102f061092c565b005b61030c600480360381019061030791906122f1565b61092e565b60405161031991906121e6565b60405180910390f35b61033c6004803603810190610337919061233e565b610994565b60405161034991906121e6565b60405180910390f35b61036c60048036038101906103679190612201565b6109c8565b6040516103799190612271565b60405180910390f35b61039c60048036038101906103979190612201565b6109ef565b005b6103b860048036038101906103b39190612391565b610a21565b6040516103c591906121e6565b60405180910390f35b6103d6610a55565b6040516103e3919061210e565b60405180910390f35b6103f4610a6d565b604051610401919061210e565b60405180910390f35b610412610a85565b60405161041f919061210e565b60405180910390f35b610442600480360381019061043d9190612391565b610a9d565b005b61044c610acf565b604051610459919061210e565b60405180910390f35b61046a610ae7565b604051610477919061210e565b60405180910390f35b610488610aff565b604051610495919061210e565b60405180910390f35b6104b860048036038101906104b39190612201565b610b17565b6040516104c59190612271565b60405180910390f35b6104e860048036038101906104e39190612414565b610b3e565b005b6104f2610b70565b6040516104ff9190612271565b60405180910390f35b610510610b94565b60405161051d9190612271565b60405180910390f35b61052e610bbc565b60405161053b919061210e565b60405180910390f35b61054c610bd4565b604051610559919061210e565b60405180910390f35b61056a610bec565b604051610577919061210e565b60405180910390f35b61059a60048036038101906105959190612414565b610c04565b005b6105a4610c36565b6040516105b19190612532565b60405180910390f35b6105d460048036038101906105cf9190612391565b610c45565b005b6105f060048036038101906105eb919061218b565b610c77565b6040516105fd91906121e6565b60405180910390f35b61060e610cab565b60405161061b919061210e565b60405180910390f35b61062c610cc3565b604051610639919061210e565b60405180910390f35b61064a610cdb565b6040516106579190612271565b60405180910390f35b610668610ce7565b6040516106759190612271565b60405180910390f35b61069860048036038101906106939190612554565b610d0b565b6040516106a59190612271565b60405180910390f35b6106b6610d3f565b6040516106c3919061210e565b60405180910390f35b6106d4610d57565b005b6106de610d59565b6040516106eb919061210e565b60405180910390f35b6106fc610d71565b60405161070991906121e6565b60405180910390f35b61072c60048036038101906107279190612391565b610da5565b604051610739919061210e565b60405180910390f35b61075c60048036038101906107579190612201565b610dd0565b60405161076a92919061262d565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156107af576107ae61265d565b5b6040519080825280602002602001820160405280156107dd5781602001602082028036833780820191505090505b50905060005b7f000000000000000000000000000000000000000000000000000000000000000081101561084057670de0b6b3a76400008282815181106108275761082661268c565b5b60200260200101818152505080806001019150506107e3565b5090565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b838390508110156109885761096d8484838181106109535761095261268c565b5b90506020020160208101906109689190612201565b611548565b61097b57600091505061098e565b8080600101915050610932565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006109d382611548565b6109de5760006109e8565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73a7241994267682de4de7ef62f52dc2c783d1784b81565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b736eed457c20603edae50c3a112caa1a9425321bd081565b6000610b2282611548565b610b2d576000610b37565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73281754ab58391a478b7aa4e7f39991cfb41118c481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610c406119a0565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b565b732f85824b2b38f179e451988670935d315b5b969281565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610daf6119a0565b8281518110610dc157610dc061268c565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e5b57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611543565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610ee257826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611543565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f6957826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611543565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fd357826040518060600160405280602281526020016126df6022913991509150611543565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361105a57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611543565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110c457826040518060600160405280602381526020016126bc6023913991509150611543565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361114b57826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611543565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111b557826040518060600160405280602781526020016127256027913991509150611543565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361123c57826040518060400160405280601981526020017f68747470733a2f2f756d622e686173686b65792e636c6f75640000000000000081525091509150611543565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112a657826040518060600160405280602481526020016127016024913991509150611543565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361132d57826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611543565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113b457826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611543565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361143b57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611543565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114a5578260405180606001604052806023815260200161274c6023913991509150611543565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152c57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611543565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806115d7575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061162157507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061166b575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116b557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116ff575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061174957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611793575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806117dd5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611827575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061187157507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806118bb5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611905575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061194f5750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611999575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156119de576119dd61265d565b5b604051908082528060200260200182016040528015611a0c5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611a3857611a3761268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611a9b57611a9a61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611afe57611afd61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611b6157611b6061268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac81600481518110611bc457611bc361268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a3881600581518110611c2757611c2661268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa471965311181600681518110611c8a57611c8961268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b81600781518110611ced57611cec61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff2714481600881518110611d5057611d4f61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600981518110611db357611db261268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600a81518110611e1657611e1561268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600b81518110611e7957611e7861268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600c81518110611edc57611edb61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081600d81518110611f3f57611f3e61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81600e81518110611fa257611fa161268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6120228161200f565b82525050565b60006120348383612019565b60208301905092915050565b6000602082019050919050565b600061205882611fe3565b6120628185611fee565b935061206d83611fff565b8060005b8381101561209e5781516120858882612028565b975061209083612040565b925050600181019050612071565b5085935050505092915050565b600060208201905081810360008301526120c5818461204d565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006120f8826120cd565b9050919050565b612108816120ed565b82525050565b600060208201905061212360008301846120ff565b92915050565b600080fd5b600080fd5b61213c816120ed565b811461214757600080fd5b50565b60008135905061215981612133565b92915050565b6121688161200f565b811461217357600080fd5b50565b6000813590506121858161215f565b92915050565b600080604083850312156121a2576121a1612129565b5b60006121b08582860161214a565b92505060206121c185828601612176565b9150509250929050565b60008115159050919050565b6121e0816121cb565b82525050565b60006020820190506121fb60008301846121d7565b92915050565b60006020828403121561221757612216612129565b5b60006122258482850161214a565b91505092915050565b6000819050919050565b6122418161222e565b82525050565b600060208201905061225c6000830184612238565b92915050565b61226b8161200f565b82525050565b60006020820190506122866000830184612262565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126122b1576122b061228c565b5b8235905067ffffffffffffffff8111156122ce576122cd612291565b5b6020830191508360208202830111156122ea576122e9612296565b5b9250929050565b6000806020838503121561230857612307612129565b5b600083013567ffffffffffffffff8111156123265761232561212e565b5b6123328582860161229b565b92509250509250929050565b60008060006060848603121561235757612356612129565b5b60006123658682870161214a565b93505060206123768682870161214a565b925050604061238786828701612176565b9150509250925092565b6000602082840312156123a7576123a6612129565b5b60006123b584828501612176565b91505092915050565b60008083601f8401126123d4576123d361228c565b5b8235905067ffffffffffffffff8111156123f1576123f0612291565b5b60208301915083600182028301111561240d5761240c612296565b5b9250929050565b60008060006040848603121561242d5761242c612129565b5b600061243b8682870161214a565b935050602084013567ffffffffffffffff81111561245c5761245b61212e565b5b612468868287016123be565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6124a9816120ed565b82525050565b60006124bb83836124a0565b60208301905092915050565b6000602082019050919050565b60006124df82612474565b6124e9818561247f565b93506124f483612490565b8060005b8381101561252557815161250c88826124af565b9750612517836124c7565b9250506001810190506124f8565b5085935050505092915050565b6000602082019050818103600083015261254c81846124d4565b905092915050565b6000806040838503121561256b5761256a612129565b5b60006125798582860161214a565b925050602061258a8582860161214a565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156125ce5780820151818401526020810190506125b3565b838111156125dd576000848401525b50505050565b6000601f19601f8301169050919050565b60006125ff82612594565b612609818561259f565b93506126198185602086016125b0565b612622816125e3565b840191505092915050565b600060408201905061264260008301856120ff565b818103602083015261265481846125f4565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6da2646970667358221220b875faa4ff94a6ed380db1c82cfc4fcfdce28d00988b3f85c113e0332affbaa264736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/polygon_production/UmbrellaFeeds.json b/deployments/polygon_production/UmbrellaFeeds.json index db2cb6c4..290b2e0c 100644 --- a/deployments/polygon_production/UmbrellaFeeds.json +++ b/deployments/polygon_production/UmbrellaFeeds.json @@ -1,5 +1,5 @@ { - "address": "0x648F235ec0C24fe170BD0822d2FEf442880A25EE", + "address": "0xb7Aa02462774f658aDef067f6999639FfeA884c6", "abi": [ { "inputs": [ @@ -662,35 +662,35 @@ "type": "function" } ], - "transactionHash": "0xff9fd26975d440c7abdb05dbb5880a180488a6d66228d3a4618dbac6518e613a", + "transactionHash": "0xdc1f04f19f879d7e42a94c3e62bec8f17f01a9c17b16c1847e911eb088109c57", "receipt": { "to": null, "from": "0xA6e4fFa19B213AbeA258ae72e8e1a209B9E543e7", - "contractAddress": "0x648F235ec0C24fe170BD0822d2FEf442880A25EE", - "transactionIndex": 39, - "gasUsed": "2533560", - "logsBloom": "0x00000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000800800000000000000000000100000000000000000000000000000000000000000000000000000000000080000000000020000000000000000000000000000000000000000000000000000002000000000000a00000000000000000000000000000000000000000000000010000000000004000000000000000000001000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000", - "blockHash": "0xf6c22c0e86a81947e46d7475d7b80787cd8f93fe2037a179c28074ec368f85bf", - "transactionHash": "0xff9fd26975d440c7abdb05dbb5880a180488a6d66228d3a4618dbac6518e613a", + "contractAddress": "0xb7Aa02462774f658aDef067f6999639FfeA884c6", + "transactionIndex": 79, + "gasUsed": "2534346", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000800000000000400000000100000000000000000000000000000000000000000000000000000000000080000000000020000000000000000000000000000000000000000000000000000002000000000000200000000000000000000000000000000000000000000000010000000000004000000000000000000001000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000", + "blockHash": "0xc6842d4330ca9831911ac2e719e222c8127af695f145988c32b575b564eac11c", + "transactionHash": "0xdc1f04f19f879d7e42a94c3e62bec8f17f01a9c17b16c1847e911eb088109c57", "logs": [ { - "transactionIndex": 39, - "blockNumber": 49650383, - "transactionHash": "0xff9fd26975d440c7abdb05dbb5880a180488a6d66228d3a4618dbac6518e613a", + "transactionIndex": 79, + "blockNumber": 63724225, + "transactionHash": "0xdc1f04f19f879d7e42a94c3e62bec8f17f01a9c17b16c1847e911eb088109c57", "address": "0x0000000000000000000000000000000000001010", "topics": [ "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63", "0x0000000000000000000000000000000000000000000000000000000000001010", "0x000000000000000000000000a6e4ffa19b213abea258ae72e8e1a209b9e543e7", - "0x000000000000000000000000ea105ab4e3f01f7f8da09cb84ab501aeb02e9fc7" + "0x0000000000000000000000007c7379531b2aee82e4ca06d4175d13b9cbeafd49" ], - "data": "0x0000000000000000000000000000000000000000000000000154efc70ef96c60000000000000000000000000000000000000000000000000a31030d2b68c0960000000000000000000000000000000000000000000000017ff22738eaf7bc1ac000000000000000000000000000000000000000000000000a1bb410ba7929d0000000000000000000000000000000000000000000000001800776355be752e0c", - "logIndex": 940, - "blockHash": "0xf6c22c0e86a81947e46d7475d7b80787cd8f93fe2037a179c28074ec368f85bf" + "data": "0x000000000000000000000000000000000000000000000000012b2c3477090014000000000000000000000000000000000000000000000000313e564dc37a315c00000000000000000000000000000000000000000003413c7a68b4a33c197d6100000000000000000000000000000000000000000000000030132a194c71314800000000000000000000000000000000000000000003413c7b93e0d7b3227d75", + "logIndex": 625, + "blockHash": "0xc6842d4330ca9831911ac2e719e222c8127af695f145988c32b575b564eac11c" } ], - "blockNumber": 49650383, - "cumulativeGasUsed": "23787055", + "blockNumber": 63724225, + "cumulativeGasUsed": "19338812", "status": 1, "byzantium": true }, @@ -700,7 +700,7 @@ 8 ], "numDeployments": 1, - "solcInputHash": "82105e144290a028d5895d7fbb79833b", + "solcInputHash": "dc68422c0ad35a4fe46d461b096b9383", "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"_contractRegistry\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"_requiredSignatures\",\"type\":\"uint16\"},{\"internalType\":\"uint8\",\"name\":\"_decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ArraysDataDoNotMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractInUse\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractNotInitialised\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ECDSAInvalidSignatureS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ECDSAInvalidSignatureV\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FeedNotExist\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRequiredSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotEnoughSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OldData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfOrder\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DECIMALS\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DEPLOYED_AT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ETH_PREFIX\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NAME\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REGISTRY\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REQUIRED_SIGNATURES\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"STAKING_BANK\",\"outputs\":[{\"internalType\":\"contract IStakingBankStatic\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"destroy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_keys\",\"type\":\"bytes32[]\"}],\"name\":\"getManyPriceData\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData[]\",\"name\":\"data\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_keys\",\"type\":\"bytes32[]\"}],\"name\":\"getManyPriceDataRaw\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData[]\",\"name\":\"data\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getPrice\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getPriceData\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData\",\"name\":\"data\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"getPriceDataByName\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData\",\"name\":\"data\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getPriceTimestamp\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getPriceTimestampHeartbeat\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_priceKeys\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData[]\",\"name\":\"_priceDatas\",\"type\":\"tuple[]\"}],\"name\":\"hashData\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"prices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData\",\"name\":\"data\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_hash\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"_v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"_r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_s\",\"type\":\"bytes32\"}],\"name\":\"recoverSigner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_priceKeys\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData[]\",\"name\":\"_priceDatas\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"struct IUmbrellaFeeds.Signature[]\",\"name\":\"_signatures\",\"type\":\"tuple[]\"}],\"name\":\"update\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_hash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"struct IUmbrellaFeeds.Signature[]\",\"name\":\"_signatures\",\"type\":\"tuple[]\"}],\"name\":\"verifySignatures\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Main contract for all on-chain data. Check `UmbrellaFeedsReader` to see how to integrate.\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_contractRegistry\":\"Registry address\",\"_decimals\":\"decimals for prices stored in this contract\",\"_requiredSignatures\":\"number of required signatures for accepting consensus submission\"}},\"destroy(string)\":{\"details\":\"destroys old contract there is sanity check that prevents abuse of destroy method\",\"params\":{\"_name\":\"string feed key to verify, that contract was initialised\"}},\"getManyPriceData(bytes32[])\":{\"details\":\"it will return array of price datas for provided `_keys` In case ony of feed does not exist, fallback call will be executed for that feed.\",\"params\":{\"_keys\":\"array of feed keys\"},\"returns\":{\"data\":\"PriceData array\"}},\"getManyPriceDataRaw(bytes32[])\":{\"details\":\"same as getManyPriceData() but does not revert on empty data.\"},\"getName()\":{\"details\":\"to follow Registrable interface\"},\"getPrice(bytes32)\":{\"params\":{\"_key\":\"hash of feed name\"},\"returns\":{\"price\":\"price\"}},\"getPriceData(bytes32)\":{\"details\":\"this is main endpoint for reading feeds. In case timestamp is empty (that means there is no data), contract will revert. If you do not need whole data from `PriceData` struct, you can save some gas by using other view methods that returns just what you need.\",\"params\":{\"_key\":\"hash of feed name\"},\"returns\":{\"data\":\"full PriceData struct\"}},\"getPriceDataByName(string)\":{\"details\":\"This method should be used only for Layer2 as it is more gas consuming than others views.\",\"params\":{\"_name\":\"string feed name\"},\"returns\":{\"data\":\"PriceData\"}},\"getPriceTimestamp(bytes32)\":{\"params\":{\"_key\":\"hash of feed name\"},\"returns\":{\"price\":\"price\",\"timestamp\":\"timestamp\"}},\"getPriceTimestampHeartbeat(bytes32)\":{\"params\":{\"_key\":\"hash of feed name\"},\"returns\":{\"heartbeat\":\"heartbeat\",\"price\":\"price\",\"timestamp\":\"timestamp\"}},\"hashData(bytes32[],(uint8,uint24,uint32,uint128)[])\":{\"details\":\"helper method for QA purposes\",\"returns\":{\"_0\":\"hash of data that are signed by validators (keys and priced data)\"}},\"prices(bytes32)\":{\"params\":{\"_key\":\"hash of feed name\"},\"returns\":{\"data\":\"full PriceData struct\"}},\"recoverSigner(bytes32,uint8,bytes32,bytes32)\":{\"params\":{\"_hash\":\"hashed of data\",\"_r\":\"part of signature\",\"_s\":\"part of signature\",\"_v\":\"part of signature\"},\"returns\":{\"_0\":\"signer address\"}},\"update(bytes32[],(uint8,uint24,uint32,uint128)[],(uint8,bytes32,bytes32)[])\":{\"details\":\"method for submitting consensus data\",\"params\":{\"_priceDatas\":\"PriceData signed by validators\",\"_priceKeys\":\"array of keys for `_priceDatas`\",\"_signatures\":\"validators signatures\"}},\"verifySignatures(bytes32,(uint8,bytes32,bytes32)[])\":{\"params\":{\"_hash\":\"hash of signed data\",\"_signatures\":\"array of validators signatures\"}}},\"stateVariables\":{\"DECIMALS\":{\"details\":\"decimals for prices stored in this contract\"},\"DEPLOYED_AT\":{\"details\":\"deployment time, used for protect for unintentional destroy\"},\"REGISTRY\":{\"details\":\"Registry contract where list of all addresses is stored. Fallback feature uses this registry to resolve newest `UmbrellaFeeds` address\"},\"REQUIRED_SIGNATURES\":{\"details\":\"minimal number of signatures required for accepting price submission (PoA)\"},\"STAKING_BANK\":{\"details\":\"StakingBank contract where list of validators is stored\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getManyPriceData(bytes32[])\":{\"notice\":\"If data for any key not exists, function will revert. Use `getManyPriceDataRaw` method if you don't want revert.\"},\"getManyPriceDataRaw(bytes32[])\":{\"notice\":\"This method does no revert if some data does not exists. Check `data.timestamp` to see if price exist, if it is 0, then it does not exist.\"},\"getPrice(bytes32)\":{\"notice\":\"method will revert if data for `_key` not exists.\"},\"getPriceData(bytes32)\":{\"notice\":\"method will revert if data for `_key` not exists.\"},\"getPriceDataByName(string)\":{\"notice\":\"It does not revert on empty data.\"},\"getPriceTimestamp(bytes32)\":{\"notice\":\"method will revert if data for `_key` not exists.\"},\"getPriceTimestampHeartbeat(bytes32)\":{\"notice\":\"method will revert if data for `_key` not exists.\"},\"prices(bytes32)\":{\"notice\":\"reader for mapping\"}},\"notice\":\"This contract can be destroyed and replaced with new one (with new address). For best gas efficiency you should pick one of two ways of integration: 1. make `UmbrellaFeeds` immutable and use fallback in case of selfdestruct. After new deployment, it is recommended to update address to avoid fallback and reduce gas cost to minimum. In long run this is most efficient solution, better than any proxy. 2. always check newest `UmbrellaFeeds` via `Regostry` and fallback will not be needed.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/onChainFeeds/UmbrellaFeeds.sol\":\"UmbrellaFeeds\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":0},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/interfaces/IRegistry.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\n\\ninterface IRegistry {\\n event LogRegistered(address indexed destination, bytes32 name);\\n\\n /// @dev imports new contract addresses and override old addresses, if they exist under provided name\\n /// This method can be used for contracts that for some reason do not have `getName` method\\n /// @param _names array of contract names that we want to register\\n /// @param _destinations array of contract addresses\\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external;\\n\\n /// @dev imports new contracts and override old addresses, if they exist.\\n /// Names of contracts are fetched directly from each contract by calling `getName`\\n /// @param _destinations array of contract addresses\\n function importContracts(address[] calldata _destinations) external;\\n\\n /// @dev this method ensure, that old and new contract is aware of it state in registry\\n /// Note: BSC registry does not have this method. This method was introduced in later stage.\\n /// @param _newContract address of contract that will replace old one\\n function atomicUpdate(address _newContract) external;\\n\\n /// @dev similar to `getAddress` but throws when contract name not exists\\n /// @param name contract name\\n /// @return contract address registered under provided name or throws, if does not exists\\n function requireAndGetAddress(bytes32 name) external view returns (address);\\n\\n /// @param name contract name in a form of bytes32\\n /// @return contract address registered under provided name\\n function getAddress(bytes32 name) external view returns (address);\\n\\n /// @param _name contract name\\n /// @return contract address assigned to the name or address(0) if not exists\\n function getAddressByString(string memory _name) external view returns (address);\\n\\n /// @dev helper method that converts string to bytes32,\\n /// you can use to to generate contract name\\n function stringToBytes32(string memory _string) external pure returns (bytes32 result);\\n}\\n\",\"keccak256\":\"0xa0099ecf4182138fda7a0733407784461410c245de67c1e7ba7cd7c9595e054f\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBank.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IStakingBank is IERC20 {\\n /// @param id address of validator wallet\\n /// @param location URL of the validator API\\n struct Validator {\\n address id;\\n string location;\\n }\\n\\n event LogValidatorRegistered(address indexed id);\\n event LogValidatorUpdated(address indexed id);\\n event LogValidatorRemoved(address indexed id);\\n event LogMinAmountForStake(uint256 minAmountForStake);\\n\\n /// @dev setter for `minAmountForStake`\\n function setMinAmountForStake(uint256 _minAmountForStake) external;\\n\\n /// @dev allows to stake `token` by validators\\n /// Validator needs to approve StakingBank beforehand\\n /// @param _value amount of tokens to stake\\n function stake(uint256 _value) external;\\n\\n /// @dev notification about approval from `_from` address on UMB token\\n /// Staking bank will stake max approved amount from `_from` address\\n /// @param _from address which approved token spend for IStakingBank\\n function receiveApproval(address _from) external returns (bool success);\\n\\n /// @dev withdraws stake tokens\\n /// it throws, when balance will be less than required minimum for stake\\n /// to withdraw all use `exit`\\n function withdraw(uint256 _value) external returns (bool success);\\n\\n /// @dev unstake and withdraw all tokens\\n function exit() external returns (bool success);\\n\\n /// @dev creates (register) new validator\\n /// @param _id validator address\\n /// @param _location location URL of the validator API\\n function create(address _id, string calldata _location) external;\\n\\n /// @dev removes validator\\n /// @param _id validator wallet\\n function remove(address _id) external;\\n\\n /// @dev updates validator location\\n /// @param _id validator wallet\\n /// @param _location new validator URL\\n function update(address _id, string calldata _location) external;\\n\\n /// @return total number of registered validators (with and without balance)\\n function getNumberOfValidators() external view returns (uint256);\\n\\n /// @dev gets validator address for provided index\\n /// @param _ix index in array of list of all validators wallets\\n function addresses(uint256 _ix) external view returns (address);\\n\\n /// @param _id address of validator\\n /// @return id address of validator\\n /// @return location URL of validator\\n function validators(address _id) external view returns (address id, string memory location);\\n}\\n\",\"keccak256\":\"0x2c518aeab8b0b3a364fafaec559d3ff0dc6a119f8d203fa31ef7ad667ca0f7b9\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBankStatic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./IStakingBank.sol\\\";\\n\\n\\ninterface IStakingBankStatic is IStakingBank {\\n /// @param _validators array of validators addresses to verify\\n /// @return TRUE when all validators are valid, FALSE otherwise\\n function verifyValidators(address[] calldata _validators) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xb7829f090205357ae8c7b86490504897060650c149309362b95eacbeef88d8ba\",\"license\":\"MIT\"},\"contracts/interfaces/IUmbrellaFeeds.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IUmbrellaFeeds {\\n struct PriceData {\\n /// @dev this is placeholder, that can be used for some additional data\\n /// atm of creating this smart contract, it is only used as marker for removed data (when == type(uint8).max)\\n uint8 data;\\n /// @dev heartbeat: how often price data will be refreshed in case price stay flat\\n uint24 heartbeat;\\n /// @dev timestamp: price time, at this time validators run consensus\\n uint32 timestamp;\\n /// @dev price\\n uint128 price;\\n }\\n\\n struct Signature {\\n uint8 v;\\n bytes32 r;\\n bytes32 s;\\n }\\n\\n /// @dev method for submitting consensus data\\n /// @param _priceKeys array of keys for `_priceDatas`\\n /// @param _priceDatas PriceData signed by validators\\n /// @param _signatures validators signatures\\n function update(\\n bytes32[] calldata _priceKeys,\\n PriceData[] calldata _priceDatas,\\n Signature[] calldata _signatures\\n ) external;\\n\\n /// @dev it will return array of price datas for provided `_keys`\\n /// In case ony of feed does not exist, fallback call will be executed for that feed.\\n /// @notice If data for any key not exists, function will revert. Use `getManyPriceDataRaw` method if you don't\\n /// want revert.\\n /// @param _keys array of feed keys\\n /// @return data PriceData array\\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data);\\n\\n /// @dev same as getManyPriceData() but does not revert on empty data.\\n /// @notice This method does no revert if some data does not exists.\\n /// Check `data.timestamp` to see if price exist, if it is 0, then it does not exist.\\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data);\\n\\n /// @dev this is main endpoint for reading feeds.\\n /// In case timestamp is empty (that means there is no data), contract will revert.\\n /// If you do not need whole data from `PriceData` struct, you can save some gas by using other view methods that\\n /// returns just what you need.\\n /// @notice method will revert if data for `_key` not exists.\\n /// @param _key hash of feed name\\n /// @return data full PriceData struct\\n function getPriceData(bytes32 _key) external view returns (PriceData memory data);\\n\\n /// @notice reader for mapping\\n /// @param _key hash of feed name\\n /// @return data full PriceData struct\\n function prices(bytes32 _key) external view returns (PriceData memory data);\\n\\n /// @notice method will revert if data for `_key` not exists.\\n /// @param _key hash of feed name\\n /// @return price\\n function getPrice(bytes32 _key) external view returns (uint128 price);\\n\\n /// @notice method will revert if data for `_key` not exists.\\n /// @param _key hash of feed name\\n /// @return price\\n /// @return timestamp\\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp);\\n\\n /// @notice method will revert if data for `_key` not exists.\\n /// @param _key hash of feed name\\n /// @return price\\n /// @return timestamp\\n /// @return heartbeat\\n function getPriceTimestampHeartbeat(bytes32 _key)\\n external\\n view\\n returns (uint128 price, uint32 timestamp, uint24 heartbeat);\\n\\n /// @dev This method should be used only for Layer2 as it is more gas consuming than others views.\\n /// @notice It does not revert on empty data.\\n /// @param _name string feed name\\n /// @return data PriceData\\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data);\\n\\n /// @dev decimals for prices stored in this contract\\n function DECIMALS() external view returns (uint8); // solhint-disable-line func-name-mixedcase\\n}\\n\",\"keccak256\":\"0x3b89742a9ab465f00aa9cf8635a5dfdc02d7ecf9bad8f564bee7c15d8aea46cb\",\"license\":\"MIT\"},\"contracts/onChainFeeds/UmbrellaFeeds.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"../interfaces/IUmbrellaFeeds.sol\\\";\\nimport \\\"../interfaces/IRegistry.sol\\\";\\nimport \\\"../interfaces/IStakingBankStatic.sol\\\";\\n\\n/// @dev Main contract for all on-chain data.\\n/// Check `UmbrellaFeedsReader` to see how to integrate.\\n///\\n/// @notice This contract can be destroyed and replaced with new one (with new address).\\n/// For best gas efficiency you should pick one of two ways of integration:\\n/// 1. make `UmbrellaFeeds` immutable and use fallback in case of selfdestruct. After new deployment, it is recommended\\n/// to update address to avoid fallback and reduce gas cost to minimum. In long run this is most efficient solution,\\n/// better than any proxy.\\n/// 2. always check newest `UmbrellaFeeds` via `Regostry` and fallback will not be needed.\\ncontract UmbrellaFeeds is IUmbrellaFeeds {\\n bytes constant public ETH_PREFIX = \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\";\\n string constant public NAME = \\\"UmbrellaFeeds\\\";\\n\\n /// @dev deployment time, used for protect for unintentional destroy\\n uint256 public immutable DEPLOYED_AT; // solhint-disable-line var-name-mixedcase\\n\\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\\n /// resolve newest `UmbrellaFeeds` address\\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\\n\\n /// @dev StakingBank contract where list of validators is stored\\n IStakingBankStatic public immutable STAKING_BANK; // solhint-disable-line var-name-mixedcase\\n\\n /// @dev minimal number of signatures required for accepting price submission (PoA)\\n uint16 public immutable REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\\n\\n /// @dev decimals for prices stored in this contract\\n uint8 public immutable DECIMALS; // solhint-disable-line var-name-mixedcase\\n\\n /// @notice map of all prices stored in this contract, key for map is hash of feed name\\n /// eg for \\\"ETH-USD\\\" feed, key will be hash(\\\"ETH-USD\\\")\\n mapping (bytes32 => PriceData) private _prices;\\n\\n error ArraysDataDoNotMatch();\\n error FeedNotExist();\\n error NotEnoughSignatures();\\n error InvalidSigner();\\n error InvalidRequiredSignatures();\\n error SignaturesOutOfOrder();\\n error ECDSAInvalidSignatureS();\\n error ECDSAInvalidSignatureV();\\n error OldData();\\n error ContractInUse();\\n error ContractNotInitialised();\\n\\n /// @param _contractRegistry Registry address\\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\\n /// @param _decimals decimals for prices stored in this contract\\n constructor(\\n IRegistry _contractRegistry,\\n uint16 _requiredSignatures,\\n uint8 _decimals\\n ) {\\n if (_requiredSignatures == 0) revert InvalidRequiredSignatures();\\n\\n REGISTRY = _contractRegistry;\\n REQUIRED_SIGNATURES = _requiredSignatures;\\n STAKING_BANK = IStakingBankStatic(_contractRegistry.requireAndGetAddress(\\\"StakingBank\\\"));\\n DECIMALS = _decimals;\\n DEPLOYED_AT = block.timestamp;\\n }\\n\\n /// @dev destroys old contract\\n /// there is sanity check that prevents abuse of destroy method\\n /// @param _name string feed key to verify, that contract was initialised\\n function destroy(string calldata _name) external {\\n if (REGISTRY.getAddressByString(NAME) == address(this)) revert ContractInUse();\\n\\n if (_prices[keccak256(abi.encodePacked(_name))].timestamp == 0 && DEPLOYED_AT + 3 days > block.timestamp) {\\n revert ContractNotInitialised();\\n }\\n\\n selfdestruct(payable(msg.sender));\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function update(\\n bytes32[] calldata _priceKeys,\\n PriceData[] calldata _priceDatas,\\n Signature[] calldata _signatures\\n ) external {\\n if (_priceKeys.length != _priceDatas.length) revert ArraysDataDoNotMatch();\\n\\n bytes32 priceDataHash = keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\\n verifySignatures(priceDataHash, _signatures);\\n\\n uint256 i;\\n\\n while (i < _priceDatas.length) {\\n bytes32 priceKey = _priceKeys[i];\\n\\n // we do not allow for older prices\\n // at the same time it prevents from reusing signatures\\n if (_prices[priceKey].timestamp >= _priceDatas[i].timestamp) revert OldData();\\n\\n _prices[priceKey] = _priceDatas[i];\\n\\n // atm there is no need for events, so in order to save gas, we do not emit any\\n unchecked { i++; }\\n }\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\\n data = new PriceData[](_keys.length);\\n\\n for (uint256 i; i < _keys.length;) {\\n data[i] = _prices[_keys[i]];\\n if (data[i].timestamp == 0) revert FeedNotExist();\\n\\n unchecked { i++; }\\n }\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\\n data = new PriceData[](_keys.length);\\n\\n for (uint256 i; i < _keys.length;) {\\n data[i] = _prices[_keys[i]];\\n unchecked { i++; }\\n }\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function prices(bytes32 _key) external view returns (PriceData memory data) {\\n data = _prices[_key];\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getPriceData(bytes32 _key) external view returns (PriceData memory data) {\\n data = _prices[_key];\\n if (data.timestamp == 0) revert FeedNotExist();\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getPrice(bytes32 _key) external view returns (uint128 price) {\\n PriceData memory data = _prices[_key];\\n if (data.timestamp == 0) revert FeedNotExist();\\n\\n return data.price;\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp) {\\n PriceData memory data = _prices[_key];\\n if (data.timestamp == 0) revert FeedNotExist();\\n\\n return (data.price, data.timestamp);\\n }\\n\\n function getPriceTimestampHeartbeat(bytes32 _key)\\n external\\n view\\n returns (uint128 price, uint32 timestamp, uint24 heartbeat)\\n {\\n PriceData memory data = _prices[_key];\\n if (data.timestamp == 0) revert FeedNotExist();\\n\\n return (data.price, data.timestamp, data.heartbeat);\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data) {\\n bytes32 key = keccak256(abi.encodePacked(_name));\\n data = _prices[key];\\n }\\n\\n /// @dev helper method for QA purposes\\n /// @return hash of data that are signed by validators (keys and priced data)\\n function hashData(bytes32[] calldata _priceKeys, PriceData[] calldata _priceDatas)\\n external\\n view\\n returns (bytes32)\\n {\\n return keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\\n }\\n\\n /// @param _hash hash of signed data\\n /// @param _signatures array of validators signatures\\n function verifySignatures(bytes32 _hash, Signature[] calldata _signatures) public view {\\n address prevSigner = address(0x0);\\n\\n if (_signatures.length < REQUIRED_SIGNATURES) revert NotEnoughSignatures();\\n\\n address[] memory validators = new address[](REQUIRED_SIGNATURES);\\n\\n // to save gas we check only required number of signatures\\n // case, where you can have part of signatures invalid but still enough valid in total is not supported\\n for (uint256 i; i < REQUIRED_SIGNATURES;) {\\n (uint8 v, bytes32 r, bytes32 s) = (_signatures[i].v, _signatures[i].r, _signatures[i].s);\\n\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n revert ECDSAInvalidSignatureS();\\n }\\n\\n if (uint8(v) != 27 && uint8(v) != 28) revert ECDSAInvalidSignatureV();\\n\\n address signer = recoverSigner(_hash, v, r, s);\\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\\n\\n // because we check only required number of signatures, any invalid one will cause revert\\n prevSigner = signer;\\n validators[i] = signer;\\n\\n unchecked { i++; }\\n }\\n\\n // bulk verification can optimise gas when we have 5 or more validators\\n if (!STAKING_BANK.verifyValidators(validators)) revert InvalidSigner();\\n }\\n\\n function getChainId() public view returns (uint256 id) {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n id := chainid()\\n }\\n }\\n\\n /// @param _hash hashed of data\\n /// @param _v part of signature\\n /// @param _r part of signature\\n /// @param _s part of signature\\n /// @return signer address\\n function recoverSigner(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _hash));\\n return ecrecover(hash, _v, _r, _s);\\n }\\n\\n /// @dev to follow Registrable interface\\n function getName() public pure returns (bytes32) {\\n return \\\"UmbrellaFeeds\\\";\\n }\\n}\\n\",\"keccak256\":\"0xf5dcfbbdfe5a5ed6e7579246363b10cdc0aa30580fec74025e0704c2b042d369\",\"license\":\"MIT\"}},\"version\":1}", "bytecode": "0x6101206040523480156200001257600080fd5b50604051620030a4380380620030a4833981810160405281019062000038919062000286565b60008261ffff160362000077576040517f458bb42100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff16815250508161ffff1660e08161ffff16815250508273ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b8152600401620000f49062000308565b602060405180830381865afa15801562000112573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000138919062000354565b73ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff16815250508060ff166101008160ff1681525050426080818152505050505062000386565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620001bd8262000190565b9050919050565b6000620001d182620001b0565b9050919050565b620001e381620001c4565b8114620001ef57600080fd5b50565b6000815190506200020381620001d8565b92915050565b600061ffff82169050919050565b620002228162000209565b81146200022e57600080fd5b50565b600081519050620002428162000217565b92915050565b600060ff82169050919050565b620002608162000248565b81146200026c57600080fd5b50565b600081519050620002808162000255565b92915050565b600080600060608486031215620002a257620002a16200018b565b5b6000620002b286828701620001f2565b9350506020620002c58682870162000231565b9250506040620002d8868287016200026f565b9150509250925092565b7f5374616b696e6742616e6b000000000000000000000000000000000000000000815250565b60006020820190506200031e60008301620002e2565b919050565b6200032e81620001b0565b81146200033a57600080fd5b50565b6000815190506200034e8162000323565b92915050565b6000602082840312156200036d576200036c6200018b565b5b60006200037d848285016200033d565b91505092915050565b60805160a05160c05160e05161010051612caf620003f560003960006108b10152600081816104e501528181610548015281816105ba01526116980152600081816107da01526116f501526000818161045e015261107e0152600081816111fd015261127a0152612caf6000f3fe608060405234801561001057600080fd5b50600436106101125760003560e01c806306433b1b1461011757806317d7de7c1461013557806324c89a491461015357806326559877146101715780632e0f26251461018d5780632e550693146101ab57806331d98b3f146101db5780633408e4701461020b578063385e05da1461022957806343fa6211146102595780635b38adc71461028957806360846bc6146102b95780636b9c3c7c146102e95780636ebb8cd2146103055780638a1194d31461032357806395f1cf301461035457806396594f66146103705780639ac18b19146103a2578063a3f4df7e146103c0578063c65a53ad146103de578063ccc6fd69146103fc578063d45167d01461042c575b600080fd5b61011f61045c565b60405161012c91906118df565b60405180910390f35b61013d610480565b60405161014a9190611913565b60405180910390f35b61015b6104a8565b60405161016891906119c7565b60405180910390f35b61018b60048036038101906101869190611a84565b6104e1565b005b6101956108af565b6040516101a29190611b00565b60405180910390f35b6101c560048036038101906101c09190611b71565b6108d3565b6040516101d29190611d39565b60405180910390f35b6101f560048036038101906101f09190611d5b565b610a54565b6040516102029190611d97565b60405180910390f35b610213610b77565b6040516102209190611dcb565b60405180910390f35b610243600480360381019061023e9190611b71565b610b7f565b6040516102509190611d39565b60405180910390f35b610273600480360381019061026e9190611d5b565b610d5e565b6040516102809190611e3b565b60405180910390f35b6102a3600480360381019061029e9190611eac565b610e7e565b6040516102b09190611e3b565b60405180910390f35b6102d360048036038101906102ce9190611d5b565b610f89565b6040516102e09190611e3b565b60405180910390f35b61030360048036038101906102fe9190611eac565b611065565b005b61030d611278565b60405161031a9190611dcb565b60405180910390f35b61033d60048036038101906103389190611d5b565b61129c565b60405161034b929190611f08565b60405180910390f35b61036e60048036038101906103699190611f87565b6113c8565b005b61038a60048036038101906103859190611d5b565b611560565b6040516103999392919061204a565b60405180910390f35b6103aa611696565b6040516103b7919061209e565b60405180910390f35b6103c86116ba565b6040516103d5919061210e565b60405180910390f35b6103e66116f3565b6040516103f39190612151565b60405180910390f35b6104166004803603810190610411919061216c565b611717565b6040516104239190611913565b60405180910390f35b61044660048036038101906104419190612219565b61175b565b60405161045391906122a1565b60405180910390f35b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f556d6272656c6c61466565647300000000000000000000000000000000000000905090565b6040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525081565b60007f000000000000000000000000000000000000000000000000000000000000000061ffff16838390501015610544576040517fe246dc6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000061ffff1667ffffffffffffffff811115610584576105836122bc565b5b6040519080825280602002602001820160405280156105b25781602001602082028036833780820191505090505b50905060005b7f000000000000000000000000000000000000000000000000000000000000000061ffff168110156107d75760008060008787858181106105fc576105fb6122eb565b5b9050606002016000016020810190610614919061231a565b888886818110610627576106266122eb565b5b90506060020160200135898987818110610644576106436122eb565b5b905060600201604001359250925092507f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08160001c11156106b1576040517f454ffaa700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601b8360ff16141580156106c95750601c8360ff1614155b15610700576040517f1afa741400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061070e8a85858561175b565b90508073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1610610775576040517f9079f69b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8096508086868151811061078c5761078b6122eb565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508480600101955050505050506105b8565b507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16631d4f9ce0826040518263ffffffff1660e01b81526004016108319190612405565b602060405180830381865afa15801561084e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610872919061245f565b6108a8576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60608282905067ffffffffffffffff8111156108f2576108f16122bc565b5b60405190808252806020026020018201604052801561092b57816020015b610918611818565b8152602001906001900390816109105790505b50905060005b83839050811015610a4d57600080858584818110610952576109516122eb565b5b9050602002013581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681525050828281518110610a3557610a346122eb565b5b60200260200101819052508080600101915050610931565b5092915050565b6000806000808481526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603610b6a576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060600151915050919050565b600046905090565b60608282905067ffffffffffffffff811115610b9e57610b9d6122bc565b5b604051908082528060200260200182016040528015610bd757816020015b610bc4611818565b815260200190600190039081610bbc5790505b50905060005b83839050811015610d5757600080858584818110610bfe57610bfd6122eb565b5b9050602002013581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681525050828281518110610ce157610ce06122eb565b5b60200260200101819052506000828281518110610d0157610d006122eb565b5b60200260200101516040015163ffffffff1603610d4a576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8080600101915050610bdd565b5092915050565b610d66611818565b6000808381526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603610e79576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b610e86611818565b60008383604051602001610e9b9291906124cb565b6040516020818303038152906040528051906020012090506000808281526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505091505092915050565b610f91611818565b6000808381526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815250509050919050565b3073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663e8f98f886040518060400160405280600d81526020017f556d6272656c6c614665656473000000000000000000000000000000000000008152506040518263ffffffff1660e01b815260040161110a919061210e565b602060405180830381865afa158015611127573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114b9190612510565b73ffffffffffffffffffffffffffffffffffffffff1603611198576040517f8c3e700900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600084846040516020016111b09291906124cb565b60405160208183030381529060405280519060200120815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff161480156112285750426203f4807f0000000000000000000000000000000000000000000000000000000000000000611226919061256c565b115b1561125f576040517fcf51b43b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff16ff5b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060008060008581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff16036113b4576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806060015181604001519250925050915091565b838390508686905014611407576040517f0cf7902300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611411610b77565b308888888860405160200161142b96959493929190612820565b60405160208183030381529060405280519060200120905061144e8184846104e1565b60005b85859050811015611556576000888883818110611471576114706122eb565b5b90506020020135905086868381811061148d5761148c6122eb565b5b90506080020160400160208101906114a59190612877565b63ffffffff1660008083815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff161061150e576040517f1251b2f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b868683818110611521576115206122eb565b5b90506080020160008083815260200190815260200160002081816115459190612ba1565b905050818060010192505050611451565b5050505050505050565b6000806000806000808681526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603611679576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806060015181604001518260200151935093509350509193909250565b7f000000000000000000000000000000000000000000000000000000000000000081565b6040518060400160405280600d81526020017f556d6272656c6c6146656564730000000000000000000000000000000000000081525081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000611721610b77565b308686868660405160200161173b96959493929190612820565b604051602081830303815290604052805190602001209050949350505050565b6000806040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250866040516020016117a6929190612c0c565b604051602081830303815290604052805190602001209050600181868686604051600081526020016040526040516117e19493929190612c34565b6020604051602081039080840390855afa158015611803573d6000803e3d6000fd5b50505060206040510351915050949350505050565b6040518060800160405280600060ff168152602001600062ffffff168152602001600063ffffffff16815260200160006fffffffffffffffffffffffffffffffff1681525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006118a56118a061189b84611860565b611880565b611860565b9050919050565b60006118b78261188a565b9050919050565b60006118c9826118ac565b9050919050565b6118d9816118be565b82525050565b60006020820190506118f460008301846118d0565b92915050565b6000819050919050565b61190d816118fa565b82525050565b60006020820190506119286000830184611904565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561196857808201518184015260208101905061194d565b83811115611977576000848401525b50505050565b6000601f19601f8301169050919050565b60006119998261192e565b6119a38185611939565b93506119b381856020860161194a565b6119bc8161197d565b840191505092915050565b600060208201905081810360008301526119e1818461198e565b905092915050565b600080fd5b600080fd5b6119fc816118fa565b8114611a0757600080fd5b50565b600081359050611a19816119f3565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112611a4457611a43611a1f565b5b8235905067ffffffffffffffff811115611a6157611a60611a24565b5b602083019150836060820283011115611a7d57611a7c611a29565b5b9250929050565b600080600060408486031215611a9d57611a9c6119e9565b5b6000611aab86828701611a0a565b935050602084013567ffffffffffffffff811115611acc57611acb6119ee565b5b611ad886828701611a2e565b92509250509250925092565b600060ff82169050919050565b611afa81611ae4565b82525050565b6000602082019050611b156000830184611af1565b92915050565b60008083601f840112611b3157611b30611a1f565b5b8235905067ffffffffffffffff811115611b4e57611b4d611a24565b5b602083019150836020820283011115611b6a57611b69611a29565b5b9250929050565b60008060208385031215611b8857611b876119e9565b5b600083013567ffffffffffffffff811115611ba657611ba56119ee565b5b611bb285828601611b1b565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b611bf381611ae4565b82525050565b600062ffffff82169050919050565b611c1181611bf9565b82525050565b600063ffffffff82169050919050565b611c3081611c17565b82525050565b60006fffffffffffffffffffffffffffffffff82169050919050565b611c5b81611c36565b82525050565b608082016000820151611c776000850182611bea565b506020820151611c8a6020850182611c08565b506040820151611c9d6040850182611c27565b506060820151611cb06060850182611c52565b50505050565b6000611cc28383611c61565b60808301905092915050565b6000602082019050919050565b6000611ce682611bbe565b611cf08185611bc9565b9350611cfb83611bda565b8060005b83811015611d2c578151611d138882611cb6565b9750611d1e83611cce565b925050600181019050611cff565b5085935050505092915050565b60006020820190508181036000830152611d538184611cdb565b905092915050565b600060208284031215611d7157611d706119e9565b5b6000611d7f84828501611a0a565b91505092915050565b611d9181611c36565b82525050565b6000602082019050611dac6000830184611d88565b92915050565b6000819050919050565b611dc581611db2565b82525050565b6000602082019050611de06000830184611dbc565b92915050565b608082016000820151611dfc6000850182611bea565b506020820151611e0f6020850182611c08565b506040820151611e226040850182611c27565b506060820151611e356060850182611c52565b50505050565b6000608082019050611e506000830184611de6565b92915050565b60008083601f840112611e6c57611e6b611a1f565b5b8235905067ffffffffffffffff811115611e8957611e88611a24565b5b602083019150836001820283011115611ea557611ea4611a29565b5b9250929050565b60008060208385031215611ec357611ec26119e9565b5b600083013567ffffffffffffffff811115611ee157611ee06119ee565b5b611eed85828601611e56565b92509250509250929050565b611f0281611c17565b82525050565b6000604082019050611f1d6000830185611d88565b611f2a6020830184611ef9565b9392505050565b60008083601f840112611f4757611f46611a1f565b5b8235905067ffffffffffffffff811115611f6457611f63611a24565b5b602083019150836080820283011115611f8057611f7f611a29565b5b9250929050565b60008060008060008060608789031215611fa457611fa36119e9565b5b600087013567ffffffffffffffff811115611fc257611fc16119ee565b5b611fce89828a01611b1b565b9650965050602087013567ffffffffffffffff811115611ff157611ff06119ee565b5b611ffd89828a01611f31565b9450945050604087013567ffffffffffffffff8111156120205761201f6119ee565b5b61202c89828a01611a2e565b92509250509295509295509295565b61204481611bf9565b82525050565b600060608201905061205f6000830186611d88565b61206c6020830185611ef9565b612079604083018461203b565b949350505050565b600061ffff82169050919050565b61209881612081565b82525050565b60006020820190506120b3600083018461208f565b92915050565b600081519050919050565b600082825260208201905092915050565b60006120e0826120b9565b6120ea81856120c4565b93506120fa81856020860161194a565b6121038161197d565b840191505092915050565b6000602082019050818103600083015261212881846120d5565b905092915050565b600061213b826118ac565b9050919050565b61214b81612130565b82525050565b60006020820190506121666000830184612142565b92915050565b60008060008060408587031215612186576121856119e9565b5b600085013567ffffffffffffffff8111156121a4576121a36119ee565b5b6121b087828801611b1b565b9450945050602085013567ffffffffffffffff8111156121d3576121d26119ee565b5b6121df87828801611f31565b925092505092959194509250565b6121f681611ae4565b811461220157600080fd5b50565b600081359050612213816121ed565b92915050565b60008060008060808587031215612233576122326119e9565b5b600061224187828801611a0a565b945050602061225287828801612204565b935050604061226387828801611a0a565b925050606061227487828801611a0a565b91505092959194509250565b600061228b82611860565b9050919050565b61229b81612280565b82525050565b60006020820190506122b66000830184612292565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156123305761232f6119e9565b5b600061233e84828501612204565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61237c81612280565b82525050565b600061238e8383612373565b60208301905092915050565b6000602082019050919050565b60006123b282612347565b6123bc8185612352565b93506123c783612363565b8060005b838110156123f85781516123df8882612382565b97506123ea8361239a565b9250506001810190506123cb565b5085935050505092915050565b6000602082019050818103600083015261241f81846123a7565b905092915050565b60008115159050919050565b61243c81612427565b811461244757600080fd5b50565b60008151905061245981612433565b92915050565b600060208284031215612475576124746119e9565b5b60006124838482850161244a565b91505092915050565b600081905092915050565b82818337600083830152505050565b60006124b2838561248c565b93506124bf838584612497565b82840190509392505050565b60006124d88284866124a6565b91508190509392505050565b6124ed81612280565b81146124f857600080fd5b50565b60008151905061250a816124e4565b92915050565b600060208284031215612526576125256119e9565b5b6000612534848285016124fb565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061257782611db2565b915061258283611db2565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156125b7576125b661253d565b5b828201905092915050565b600082825260208201905092915050565b600080fd5b60006125e483856125c2565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115612617576126166125d3565b5b602083029250612628838584612497565b82840190509392505050565b6000819050919050565b600061264d6020840184612204565b905092915050565b61265e81611bf9565b811461266957600080fd5b50565b60008135905061267b81612655565b92915050565b6000612690602084018461266c565b905092915050565b6126a181611c17565b81146126ac57600080fd5b50565b6000813590506126be81612698565b92915050565b60006126d360208401846126af565b905092915050565b6126e481611c36565b81146126ef57600080fd5b50565b600081359050612701816126db565b92915050565b600061271660208401846126f2565b905092915050565b6080820161272f600083018361263e565b61273c6000850182611bea565b5061274a6020830183612681565b6127576020850182611c08565b5061276560408301836126c4565b6127726040850182611c27565b506127806060830183612707565b61278d6060850182611c52565b50505050565b600061279f838361271e565b60808301905092915050565b600082905092915050565b6000608082019050919050565b60006127cf8385611bc9565b93506127da82612634565b8060005b85811015612813576127f082846127ab565b6127fa8882612793565b9750612805836127b6565b9250506001810190506127de565b5085925050509392505050565b60006080820190506128356000830189611dbc565b6128426020830188612292565b81810360408301526128558186886125d8565b9050818103606083015261286a8184866127c3565b9050979650505050505050565b60006020828403121561288d5761288c6119e9565b5b600061289b848285016126af565b91505092915050565b600081356128b1816121ed565b80915050919050565b60008160001b9050919050565b600060ff6128d4846128ba565b9350801983169250808416831791505092915050565b60006129056129006128fb84611ae4565b611880565b611ae4565b9050919050565b6000819050919050565b61291f826128ea565b61293261292b8261290c565b83546128c7565b8255505050565b6000813561294681612655565b80915050919050565b60008160081b9050919050565b600063ffffff0061296c8461294f565b9350801983169250808416831791505092915050565b600061299d61299861299384611bf9565b611880565b611bf9565b9050919050565b6000819050919050565b6129b782612982565b6129ca6129c3826129a4565b835461295c565b8255505050565b600081356129de81612698565b80915050919050565b60008160201b9050919050565b600067ffffffff00000000612a08846129e7565b9350801983169250808416831791505092915050565b6000612a39612a34612a2f84611c17565b611880565b611c17565b9050919050565b6000819050919050565b612a5382612a1e565b612a66612a5f82612a40565b83546129f4565b8255505050565b60008135612a7a816126db565b80915050919050565b60008160401b9050919050565b600077ffffffffffffffffffffffffffffffff0000000000000000612ab484612a83565b9350801983169250808416831791505092915050565b6000612ae5612ae0612adb84611c36565b611880565b611c36565b9050919050565b6000819050919050565b612aff82612aca565b612b12612b0b82612aec565b8354612a90565b8255505050565b600081016000830180612b2b816128a4565b9050612b378184612916565b505050600081016020830180612b4c81612939565b9050612b5881846129ae565b505050600081016040830180612b6d816129d1565b9050612b798184612a4a565b505050600081016060830180612b8e81612a6d565b9050612b9a8184612af6565b5050505050565b612bab8282612b19565b5050565b600081905092915050565b6000612bc58261192e565b612bcf8185612baf565b9350612bdf81856020860161194a565b80840191505092915050565b6000819050919050565b612c06612c01826118fa565b612beb565b82525050565b6000612c188285612bba565b9150612c248284612bf5565b6020820191508190509392505050565b6000608082019050612c496000830187611904565b612c566020830186611af1565b612c636040830185611904565b612c706060830184611904565b9594505050505056fea26469706673582212204e20478e2e3070a20aa83127753a448e1b78b26fd4b44673d2f1b4027a2cf6be64736f6c634300080d0033", "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101125760003560e01c806306433b1b1461011757806317d7de7c1461013557806324c89a491461015357806326559877146101715780632e0f26251461018d5780632e550693146101ab57806331d98b3f146101db5780633408e4701461020b578063385e05da1461022957806343fa6211146102595780635b38adc71461028957806360846bc6146102b95780636b9c3c7c146102e95780636ebb8cd2146103055780638a1194d31461032357806395f1cf301461035457806396594f66146103705780639ac18b19146103a2578063a3f4df7e146103c0578063c65a53ad146103de578063ccc6fd69146103fc578063d45167d01461042c575b600080fd5b61011f61045c565b60405161012c91906118df565b60405180910390f35b61013d610480565b60405161014a9190611913565b60405180910390f35b61015b6104a8565b60405161016891906119c7565b60405180910390f35b61018b60048036038101906101869190611a84565b6104e1565b005b6101956108af565b6040516101a29190611b00565b60405180910390f35b6101c560048036038101906101c09190611b71565b6108d3565b6040516101d29190611d39565b60405180910390f35b6101f560048036038101906101f09190611d5b565b610a54565b6040516102029190611d97565b60405180910390f35b610213610b77565b6040516102209190611dcb565b60405180910390f35b610243600480360381019061023e9190611b71565b610b7f565b6040516102509190611d39565b60405180910390f35b610273600480360381019061026e9190611d5b565b610d5e565b6040516102809190611e3b565b60405180910390f35b6102a3600480360381019061029e9190611eac565b610e7e565b6040516102b09190611e3b565b60405180910390f35b6102d360048036038101906102ce9190611d5b565b610f89565b6040516102e09190611e3b565b60405180910390f35b61030360048036038101906102fe9190611eac565b611065565b005b61030d611278565b60405161031a9190611dcb565b60405180910390f35b61033d60048036038101906103389190611d5b565b61129c565b60405161034b929190611f08565b60405180910390f35b61036e60048036038101906103699190611f87565b6113c8565b005b61038a60048036038101906103859190611d5b565b611560565b6040516103999392919061204a565b60405180910390f35b6103aa611696565b6040516103b7919061209e565b60405180910390f35b6103c86116ba565b6040516103d5919061210e565b60405180910390f35b6103e66116f3565b6040516103f39190612151565b60405180910390f35b6104166004803603810190610411919061216c565b611717565b6040516104239190611913565b60405180910390f35b61044660048036038101906104419190612219565b61175b565b60405161045391906122a1565b60405180910390f35b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f556d6272656c6c61466565647300000000000000000000000000000000000000905090565b6040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525081565b60007f000000000000000000000000000000000000000000000000000000000000000061ffff16838390501015610544576040517fe246dc6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000061ffff1667ffffffffffffffff811115610584576105836122bc565b5b6040519080825280602002602001820160405280156105b25781602001602082028036833780820191505090505b50905060005b7f000000000000000000000000000000000000000000000000000000000000000061ffff168110156107d75760008060008787858181106105fc576105fb6122eb565b5b9050606002016000016020810190610614919061231a565b888886818110610627576106266122eb565b5b90506060020160200135898987818110610644576106436122eb565b5b905060600201604001359250925092507f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08160001c11156106b1576040517f454ffaa700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601b8360ff16141580156106c95750601c8360ff1614155b15610700576040517f1afa741400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061070e8a85858561175b565b90508073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1610610775576040517f9079f69b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8096508086868151811061078c5761078b6122eb565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508480600101955050505050506105b8565b507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16631d4f9ce0826040518263ffffffff1660e01b81526004016108319190612405565b602060405180830381865afa15801561084e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610872919061245f565b6108a8576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60608282905067ffffffffffffffff8111156108f2576108f16122bc565b5b60405190808252806020026020018201604052801561092b57816020015b610918611818565b8152602001906001900390816109105790505b50905060005b83839050811015610a4d57600080858584818110610952576109516122eb565b5b9050602002013581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681525050828281518110610a3557610a346122eb565b5b60200260200101819052508080600101915050610931565b5092915050565b6000806000808481526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603610b6a576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060600151915050919050565b600046905090565b60608282905067ffffffffffffffff811115610b9e57610b9d6122bc565b5b604051908082528060200260200182016040528015610bd757816020015b610bc4611818565b815260200190600190039081610bbc5790505b50905060005b83839050811015610d5757600080858584818110610bfe57610bfd6122eb565b5b9050602002013581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681525050828281518110610ce157610ce06122eb565b5b60200260200101819052506000828281518110610d0157610d006122eb565b5b60200260200101516040015163ffffffff1603610d4a576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8080600101915050610bdd565b5092915050565b610d66611818565b6000808381526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603610e79576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b610e86611818565b60008383604051602001610e9b9291906124cb565b6040516020818303038152906040528051906020012090506000808281526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505091505092915050565b610f91611818565b6000808381526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815250509050919050565b3073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663e8f98f886040518060400160405280600d81526020017f556d6272656c6c614665656473000000000000000000000000000000000000008152506040518263ffffffff1660e01b815260040161110a919061210e565b602060405180830381865afa158015611127573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114b9190612510565b73ffffffffffffffffffffffffffffffffffffffff1603611198576040517f8c3e700900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600084846040516020016111b09291906124cb565b60405160208183030381529060405280519060200120815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff161480156112285750426203f4807f0000000000000000000000000000000000000000000000000000000000000000611226919061256c565b115b1561125f576040517fcf51b43b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff16ff5b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060008060008581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff16036113b4576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806060015181604001519250925050915091565b838390508686905014611407576040517f0cf7902300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611411610b77565b308888888860405160200161142b96959493929190612820565b60405160208183030381529060405280519060200120905061144e8184846104e1565b60005b85859050811015611556576000888883818110611471576114706122eb565b5b90506020020135905086868381811061148d5761148c6122eb565b5b90506080020160400160208101906114a59190612877565b63ffffffff1660008083815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff161061150e576040517f1251b2f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b868683818110611521576115206122eb565b5b90506080020160008083815260200190815260200160002081816115459190612ba1565b905050818060010192505050611451565b5050505050505050565b6000806000806000808681526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603611679576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806060015181604001518260200151935093509350509193909250565b7f000000000000000000000000000000000000000000000000000000000000000081565b6040518060400160405280600d81526020017f556d6272656c6c6146656564730000000000000000000000000000000000000081525081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000611721610b77565b308686868660405160200161173b96959493929190612820565b604051602081830303815290604052805190602001209050949350505050565b6000806040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250866040516020016117a6929190612c0c565b604051602081830303815290604052805190602001209050600181868686604051600081526020016040526040516117e19493929190612c34565b6020604051602081039080840390855afa158015611803573d6000803e3d6000fd5b50505060206040510351915050949350505050565b6040518060800160405280600060ff168152602001600062ffffff168152602001600063ffffffff16815260200160006fffffffffffffffffffffffffffffffff1681525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006118a56118a061189b84611860565b611880565b611860565b9050919050565b60006118b78261188a565b9050919050565b60006118c9826118ac565b9050919050565b6118d9816118be565b82525050565b60006020820190506118f460008301846118d0565b92915050565b6000819050919050565b61190d816118fa565b82525050565b60006020820190506119286000830184611904565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561196857808201518184015260208101905061194d565b83811115611977576000848401525b50505050565b6000601f19601f8301169050919050565b60006119998261192e565b6119a38185611939565b93506119b381856020860161194a565b6119bc8161197d565b840191505092915050565b600060208201905081810360008301526119e1818461198e565b905092915050565b600080fd5b600080fd5b6119fc816118fa565b8114611a0757600080fd5b50565b600081359050611a19816119f3565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112611a4457611a43611a1f565b5b8235905067ffffffffffffffff811115611a6157611a60611a24565b5b602083019150836060820283011115611a7d57611a7c611a29565b5b9250929050565b600080600060408486031215611a9d57611a9c6119e9565b5b6000611aab86828701611a0a565b935050602084013567ffffffffffffffff811115611acc57611acb6119ee565b5b611ad886828701611a2e565b92509250509250925092565b600060ff82169050919050565b611afa81611ae4565b82525050565b6000602082019050611b156000830184611af1565b92915050565b60008083601f840112611b3157611b30611a1f565b5b8235905067ffffffffffffffff811115611b4e57611b4d611a24565b5b602083019150836020820283011115611b6a57611b69611a29565b5b9250929050565b60008060208385031215611b8857611b876119e9565b5b600083013567ffffffffffffffff811115611ba657611ba56119ee565b5b611bb285828601611b1b565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b611bf381611ae4565b82525050565b600062ffffff82169050919050565b611c1181611bf9565b82525050565b600063ffffffff82169050919050565b611c3081611c17565b82525050565b60006fffffffffffffffffffffffffffffffff82169050919050565b611c5b81611c36565b82525050565b608082016000820151611c776000850182611bea565b506020820151611c8a6020850182611c08565b506040820151611c9d6040850182611c27565b506060820151611cb06060850182611c52565b50505050565b6000611cc28383611c61565b60808301905092915050565b6000602082019050919050565b6000611ce682611bbe565b611cf08185611bc9565b9350611cfb83611bda565b8060005b83811015611d2c578151611d138882611cb6565b9750611d1e83611cce565b925050600181019050611cff565b5085935050505092915050565b60006020820190508181036000830152611d538184611cdb565b905092915050565b600060208284031215611d7157611d706119e9565b5b6000611d7f84828501611a0a565b91505092915050565b611d9181611c36565b82525050565b6000602082019050611dac6000830184611d88565b92915050565b6000819050919050565b611dc581611db2565b82525050565b6000602082019050611de06000830184611dbc565b92915050565b608082016000820151611dfc6000850182611bea565b506020820151611e0f6020850182611c08565b506040820151611e226040850182611c27565b506060820151611e356060850182611c52565b50505050565b6000608082019050611e506000830184611de6565b92915050565b60008083601f840112611e6c57611e6b611a1f565b5b8235905067ffffffffffffffff811115611e8957611e88611a24565b5b602083019150836001820283011115611ea557611ea4611a29565b5b9250929050565b60008060208385031215611ec357611ec26119e9565b5b600083013567ffffffffffffffff811115611ee157611ee06119ee565b5b611eed85828601611e56565b92509250509250929050565b611f0281611c17565b82525050565b6000604082019050611f1d6000830185611d88565b611f2a6020830184611ef9565b9392505050565b60008083601f840112611f4757611f46611a1f565b5b8235905067ffffffffffffffff811115611f6457611f63611a24565b5b602083019150836080820283011115611f8057611f7f611a29565b5b9250929050565b60008060008060008060608789031215611fa457611fa36119e9565b5b600087013567ffffffffffffffff811115611fc257611fc16119ee565b5b611fce89828a01611b1b565b9650965050602087013567ffffffffffffffff811115611ff157611ff06119ee565b5b611ffd89828a01611f31565b9450945050604087013567ffffffffffffffff8111156120205761201f6119ee565b5b61202c89828a01611a2e565b92509250509295509295509295565b61204481611bf9565b82525050565b600060608201905061205f6000830186611d88565b61206c6020830185611ef9565b612079604083018461203b565b949350505050565b600061ffff82169050919050565b61209881612081565b82525050565b60006020820190506120b3600083018461208f565b92915050565b600081519050919050565b600082825260208201905092915050565b60006120e0826120b9565b6120ea81856120c4565b93506120fa81856020860161194a565b6121038161197d565b840191505092915050565b6000602082019050818103600083015261212881846120d5565b905092915050565b600061213b826118ac565b9050919050565b61214b81612130565b82525050565b60006020820190506121666000830184612142565b92915050565b60008060008060408587031215612186576121856119e9565b5b600085013567ffffffffffffffff8111156121a4576121a36119ee565b5b6121b087828801611b1b565b9450945050602085013567ffffffffffffffff8111156121d3576121d26119ee565b5b6121df87828801611f31565b925092505092959194509250565b6121f681611ae4565b811461220157600080fd5b50565b600081359050612213816121ed565b92915050565b60008060008060808587031215612233576122326119e9565b5b600061224187828801611a0a565b945050602061225287828801612204565b935050604061226387828801611a0a565b925050606061227487828801611a0a565b91505092959194509250565b600061228b82611860565b9050919050565b61229b81612280565b82525050565b60006020820190506122b66000830184612292565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156123305761232f6119e9565b5b600061233e84828501612204565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61237c81612280565b82525050565b600061238e8383612373565b60208301905092915050565b6000602082019050919050565b60006123b282612347565b6123bc8185612352565b93506123c783612363565b8060005b838110156123f85781516123df8882612382565b97506123ea8361239a565b9250506001810190506123cb565b5085935050505092915050565b6000602082019050818103600083015261241f81846123a7565b905092915050565b60008115159050919050565b61243c81612427565b811461244757600080fd5b50565b60008151905061245981612433565b92915050565b600060208284031215612475576124746119e9565b5b60006124838482850161244a565b91505092915050565b600081905092915050565b82818337600083830152505050565b60006124b2838561248c565b93506124bf838584612497565b82840190509392505050565b60006124d88284866124a6565b91508190509392505050565b6124ed81612280565b81146124f857600080fd5b50565b60008151905061250a816124e4565b92915050565b600060208284031215612526576125256119e9565b5b6000612534848285016124fb565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061257782611db2565b915061258283611db2565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156125b7576125b661253d565b5b828201905092915050565b600082825260208201905092915050565b600080fd5b60006125e483856125c2565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115612617576126166125d3565b5b602083029250612628838584612497565b82840190509392505050565b6000819050919050565b600061264d6020840184612204565b905092915050565b61265e81611bf9565b811461266957600080fd5b50565b60008135905061267b81612655565b92915050565b6000612690602084018461266c565b905092915050565b6126a181611c17565b81146126ac57600080fd5b50565b6000813590506126be81612698565b92915050565b60006126d360208401846126af565b905092915050565b6126e481611c36565b81146126ef57600080fd5b50565b600081359050612701816126db565b92915050565b600061271660208401846126f2565b905092915050565b6080820161272f600083018361263e565b61273c6000850182611bea565b5061274a6020830183612681565b6127576020850182611c08565b5061276560408301836126c4565b6127726040850182611c27565b506127806060830183612707565b61278d6060850182611c52565b50505050565b600061279f838361271e565b60808301905092915050565b600082905092915050565b6000608082019050919050565b60006127cf8385611bc9565b93506127da82612634565b8060005b85811015612813576127f082846127ab565b6127fa8882612793565b9750612805836127b6565b9250506001810190506127de565b5085925050509392505050565b60006080820190506128356000830189611dbc565b6128426020830188612292565b81810360408301526128558186886125d8565b9050818103606083015261286a8184866127c3565b9050979650505050505050565b60006020828403121561288d5761288c6119e9565b5b600061289b848285016126af565b91505092915050565b600081356128b1816121ed565b80915050919050565b60008160001b9050919050565b600060ff6128d4846128ba565b9350801983169250808416831791505092915050565b60006129056129006128fb84611ae4565b611880565b611ae4565b9050919050565b6000819050919050565b61291f826128ea565b61293261292b8261290c565b83546128c7565b8255505050565b6000813561294681612655565b80915050919050565b60008160081b9050919050565b600063ffffff0061296c8461294f565b9350801983169250808416831791505092915050565b600061299d61299861299384611bf9565b611880565b611bf9565b9050919050565b6000819050919050565b6129b782612982565b6129ca6129c3826129a4565b835461295c565b8255505050565b600081356129de81612698565b80915050919050565b60008160201b9050919050565b600067ffffffff00000000612a08846129e7565b9350801983169250808416831791505092915050565b6000612a39612a34612a2f84611c17565b611880565b611c17565b9050919050565b6000819050919050565b612a5382612a1e565b612a66612a5f82612a40565b83546129f4565b8255505050565b60008135612a7a816126db565b80915050919050565b60008160401b9050919050565b600077ffffffffffffffffffffffffffffffff0000000000000000612ab484612a83565b9350801983169250808416831791505092915050565b6000612ae5612ae0612adb84611c36565b611880565b611c36565b9050919050565b6000819050919050565b612aff82612aca565b612b12612b0b82612aec565b8354612a90565b8255505050565b600081016000830180612b2b816128a4565b9050612b378184612916565b505050600081016020830180612b4c81612939565b9050612b5881846129ae565b505050600081016040830180612b6d816129d1565b9050612b798184612a4a565b505050600081016060830180612b8e81612a6d565b9050612b9a8184612af6565b5050505050565b612bab8282612b19565b5050565b600081905092915050565b6000612bc58261192e565b612bcf8185612baf565b9350612bdf81856020860161194a565b80840191505092915050565b6000819050919050565b612c06612c01826118fa565b612beb565b82525050565b6000612c188285612bba565b9150612c248284612bf5565b6020820191508190509392505050565b6000608082019050612c496000830187611904565b612c566020830186611af1565b612c636040830185611904565b612c706060830184611904565b9594505050505056fea26469706673582212204e20478e2e3070a20aa83127753a448e1b78b26fd4b44673d2f1b4027a2cf6be64736f6c634300080d0033", @@ -874,12 +874,12 @@ "storageLayout": { "storage": [ { - "astId": 4270, + "astId": 4239, "contract": "contracts/onChainFeeds/UmbrellaFeeds.sol:UmbrellaFeeds", "label": "_prices", "offset": 0, "slot": "0", - "type": "t_mapping(t_bytes32,t_struct(PriceData)3396_storage)" + "type": "t_mapping(t_bytes32,t_struct(PriceData)3365_storage)" } ], "types": { @@ -888,19 +888,19 @@ "label": "bytes32", "numberOfBytes": "32" }, - "t_mapping(t_bytes32,t_struct(PriceData)3396_storage)": { + "t_mapping(t_bytes32,t_struct(PriceData)3365_storage)": { "encoding": "mapping", "key": "t_bytes32", "label": "mapping(bytes32 => struct IUmbrellaFeeds.PriceData)", "numberOfBytes": "32", - "value": "t_struct(PriceData)3396_storage" + "value": "t_struct(PriceData)3365_storage" }, - "t_struct(PriceData)3396_storage": { + "t_struct(PriceData)3365_storage": { "encoding": "inplace", "label": "struct IUmbrellaFeeds.PriceData", "members": [ { - "astId": 3386, + "astId": 3355, "contract": "contracts/onChainFeeds/UmbrellaFeeds.sol:UmbrellaFeeds", "label": "data", "offset": 0, @@ -908,7 +908,7 @@ "type": "t_uint8" }, { - "astId": 3389, + "astId": 3358, "contract": "contracts/onChainFeeds/UmbrellaFeeds.sol:UmbrellaFeeds", "label": "heartbeat", "offset": 1, @@ -916,7 +916,7 @@ "type": "t_uint24" }, { - "astId": 3392, + "astId": 3361, "contract": "contracts/onChainFeeds/UmbrellaFeeds.sol:UmbrellaFeeds", "label": "timestamp", "offset": 4, @@ -924,7 +924,7 @@ "type": "t_uint32" }, { - "astId": 3395, + "astId": 3364, "contract": "contracts/onChainFeeds/UmbrellaFeeds.sol:UmbrellaFeeds", "label": "price", "offset": 8, diff --git a/deployments/polygon_production/solcInputs/dc68422c0ad35a4fe46d461b096b9383.json b/deployments/polygon_production/solcInputs/dc68422c0ad35a4fe46d461b096b9383.json new file mode 100644 index 00000000..43238985 --- /dev/null +++ b/deployments/polygon_production/solcInputs/dc68422c0ad35a4fe46d461b096b9383.json @@ -0,0 +1,125 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n }\n _balances[to] += amount;\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n _balances[account] += amount;\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n }\n _totalSupply -= amount;\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Trees proofs.\n *\n * The proofs can be generated using the JavaScript library\n * https://github.com/miguelmota/merkletreejs[merkletreejs].\n * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.\n *\n * See `test/utils/cryptography/MerkleProof.test.js` for some examples.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(\n bytes32[] memory proof,\n bytes32 root,\n bytes32 leaf\n ) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n bytes32 proofElement = proof[i];\n if (computedHash <= proofElement) {\n // Hash(current computed hash + current element of the proof)\n computedHash = _efficientHash(computedHash, proofElement);\n } else {\n // Hash(current element of the proof + current computed hash)\n computedHash = _efficientHash(proofElement, computedHash);\n }\n }\n return computedHash;\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "@umb-network/toolbox/dist/contracts/lib/ValueDecoder.sol": { + "content": "//SPDX-License-Identifier: Unlicensed\npragma solidity >=0.6.8;\n\nlibrary ValueDecoder {\n function toUint(bytes memory _bytes) internal pure returns (uint256 value) {\n assembly {\n value := mload(add(_bytes, 32))\n }\n }\n\n function toUint(bytes32 _bytes) internal pure returns (uint256 value) {\n assembly {\n value := _bytes\n }\n }\n\n function toInt(uint224 u) internal pure returns (int256) {\n int224 i;\n uint224 max = type(uint224).max;\n\n if (u <= (max - 1) / 2) { // positive values\n assembly {\n i := add(u, 0)\n }\n\n return i;\n } else { // negative values\n assembly {\n i := sub(sub(u, max), 1)\n }\n }\n\n return i;\n }\n}\n\n" + }, + "contracts/BaseChain.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\";\nimport \"@umb-network/toolbox/dist/contracts/lib/ValueDecoder.sol\";\n\nimport \"./interfaces/IBaseChainV1.sol\";\nimport \"./interfaces/IStakingBank.sol\";\nimport \"./extensions/Registrable.sol\";\nimport \"./Registry.sol\";\n\nabstract contract BaseChain is Registrable, Ownable {\n using ValueDecoder for bytes;\n using ValueDecoder for uint224;\n using MerkleProof for bytes32[];\n\n /// @param root merkle root for consensus\n /// @param dataTimestamp consensus timestamp\n struct Block {\n bytes32 root;\n uint32 dataTimestamp;\n }\n\n /// @param value FCD value\n /// @param dataTimestamp FCD timestamp\n struct FirstClassData {\n uint224 value;\n uint32 dataTimestamp;\n }\n\n /// @param blocksCountOffset number of all blocks that were generated before switching to this contract\n /// @param sequence is a total number of blocks (consensus rounds) including previous contracts\n /// @param lastTimestamp is a timestamp of last submitted block\n /// @param padding number of seconds that need to pass before new submit will be possible\n /// @param deprecated flag that changes to TRUE on `unregister`, when TRUE submissions are not longer available\n struct ConsensusData {\n uint32 blocksCountOffset;\n uint32 sequence;\n uint32 lastTimestamp;\n uint32 padding;\n bool deprecated;\n }\n\n uint256 constant public VERSION = 2;\n\n bool internal immutable _ALLOW_FOR_MIXED_TYPE; // solhint-disable-line var-name-mixedcase\n\n bytes4 constant private _VERSION_SELECTOR = bytes4(keccak256(\"VERSION()\"));\n\n /// @dev minimal number of signatures required for accepting submission (PoA)\n uint16 internal immutable _REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\n\n ConsensusData internal _consensusData;\n\n bytes constant public ETH_PREFIX = \"\\x19Ethereum Signed Message:\\n32\";\n\n /// @dev block id (consensus ID) => root\n /// consensus ID is at the same time consensus timestamp\n mapping(uint256 => bytes32) public roots;\n\n /// @dev FCD key => FCD data\n mapping(bytes32 => FirstClassData) public fcds;\n\n event LogDeprecation(address indexed deprecator);\n event LogPadding(address indexed executor, uint32 timePadding);\n\n error ArraysDataDoNotMatch();\n error AlreadyDeprecated();\n error AlreadyRegistered();\n error BlockSubmittedToFastOrDataToOld();\n error ContractNotReady();\n error FCDOverflow();\n error InvalidContractType();\n error NoChangeToState();\n error OnlyOwnerOrRegistry();\n error UnregisterFirst();\n\n modifier onlyOwnerOrRegistry () {\n if (msg.sender != address(contractRegistry) && msg.sender != owner()) revert OnlyOwnerOrRegistry();\n _;\n }\n\n /// @param _contractRegistry Registry address\n /// @param _padding required \"space\" between blocks in seconds\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n constructor(\n IRegistry _contractRegistry,\n uint32 _padding,\n uint16 _requiredSignatures,\n bool _allowForMixedType\n ) Registrable(_contractRegistry) {\n _ALLOW_FOR_MIXED_TYPE = _allowForMixedType;\n _REQUIRED_SIGNATURES = _requiredSignatures;\n\n _setPadding(_padding);\n\n BaseChain oldChain = BaseChain(_contractRegistry.getAddress(\"Chain\"));\n\n if (address(oldChain) == address(0)) {\n // if this is first contract in sidechain, then we need to initialise lastTimestamp so submission\n // can be possible\n _consensusData.lastTimestamp = uint32(block.timestamp) - _padding - 1;\n }\n }\n\n /// @dev setter for `padding`\n function setPadding(uint16 _padding) external {\n _setPadding(_padding);\n }\n\n /// @notice if this method needs to be called manually (not from Registry)\n /// it is important to do it as part of tx batch\n /// eg using multisig, we should prepare set of transactions and confirm them all at once\n /// @inheritdoc Registrable\n function register() external override onlyOwnerOrRegistry {\n address oldChain = contractRegistry.getAddress(\"Chain\");\n\n // registration must be done before address in registry is replaced\n if (oldChain == address(this)) revert AlreadyRegistered();\n\n if (oldChain == address(0x0)) {\n return;\n }\n\n _cloneLastDataFromPrevChain(oldChain);\n }\n\n /// @inheritdoc Registrable\n function unregister() external override onlyOwnerOrRegistry {\n // in case we deprecated contract manually, we simply return\n if (_consensusData.deprecated) return;\n\n address newChain = contractRegistry.getAddress(\"Chain\");\n // unregistering must be done after address in registry is replaced\n if (newChain == address(this)) revert UnregisterFirst();\n\n // TODO:\n // I think we need to remove restriction for type (at least once)\n // when we will switch to multichain architecture\n\n if (!_ALLOW_FOR_MIXED_TYPE) {\n // can not be replaced with chain of different type\n if (BaseChain(newChain).isForeign() != this.isForeign()) revert InvalidContractType();\n }\n\n _consensusData.deprecated = true;\n emit LogDeprecation(msg.sender);\n }\n\n /// @notice it allows to deprecate contract manually\n /// Only new Registry calls `unregister()` where we set deprecated to true\n /// In old Registries we don't have this feature, so in order to safely redeploy new Chain\n /// we will have to first deprecate current contract manually, then register new contract\n function deprecate() external onlyOwnerOrRegistry {\n if (_consensusData.deprecated) revert AlreadyDeprecated();\n\n _consensusData.deprecated = true;\n emit LogDeprecation(msg.sender);\n }\n\n /// @dev getter for `_consensusData`\n function getConsensusData() external view returns (ConsensusData memory) {\n return _consensusData;\n }\n\n /// @dev number of blocks (consensus rounds) saved in this contract\n function blocksCount() external view returns (uint256) {\n return _consensusData.sequence - _consensusData.blocksCountOffset;\n }\n\n function blocksCountOffset() external view returns (uint32) {\n return _consensusData.blocksCountOffset;\n }\n\n function lastBlockId() external view returns (uint256) {\n return _consensusData.lastTimestamp;\n }\n\n /// @return TRUE if contract is ForeignChain, FALSE otherwise\n function isForeign() external pure virtual returns (bool);\n\n /// @inheritdoc Registrable\n function getName() external pure override returns (bytes32) {\n return \"Chain\";\n }\n\n /// @param _affidavit root and FCDs hashed together\n /// @param _v part of signature\n /// @param _r part of signature\n /// @param _s part of signature\n /// @return signer address\n function recoverSigner(bytes32 _affidavit, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _affidavit));\n return ecrecover(hash, _v, _r, _s);\n }\n\n /// @param _blockId ID of submitted block\n /// @return block data (root + timestamp)\n function blocks(uint256 _blockId) external view returns (Block memory) {\n return Block(roots[_blockId], uint32(_blockId));\n }\n\n /// @return current block ID\n /// please note, that current ID is not the same as last ID, current means that once padding pass,\n /// ID will switch to next one and it will be pointing to empty submit until submit for that ID is done\n function getBlockId() external view returns (uint32) {\n if (_consensusData.lastTimestamp == 0) return 0;\n\n return getBlockIdAtTimestamp(block.timestamp);\n }\n\n function requiredSignatures() external view returns (uint16) {\n return _REQUIRED_SIGNATURES;\n }\n\n /// @dev calculates block ID for provided timestamp\n /// this function does not works for past timestamps\n /// @param _timestamp current or future timestamp\n /// @return block ID for provided timestamp\n function getBlockIdAtTimestamp(uint256 _timestamp) virtual public view returns (uint32) {\n ConsensusData memory data = _consensusData;\n\n unchecked {\n // we can't overflow because we adding two `uint32`\n if (data.lastTimestamp + data.padding < _timestamp) {\n return uint32(_timestamp);\n }\n }\n\n return data.lastTimestamp;\n }\n\n /// @return last submitted block ID, please note, that on deployment, when there is no submission for this contract\n /// block for last ID will be available in previous contract\n function getLatestBlockId() virtual public view returns (uint32) {\n return _consensusData.lastTimestamp;\n }\n\n /// @dev verifies if the leaf is valid leaf for merkle tree\n /// @param _proof merkle proof for merkle tree\n /// @param _root merkle root\n /// @param _leaf leaf hash\n /// @return TRUE if `_leaf` is valid, FALSE otherwise\n function verifyProof(bytes32[] memory _proof, bytes32 _root, bytes32 _leaf) public pure returns (bool) {\n if (_root == bytes32(0)) {\n return false;\n }\n\n return _proof.verify(_root, _leaf);\n }\n\n /// @dev creates leaf hash, that has is used in merkle tree\n /// @param _key key under which we store the value\n /// @param _value value itself as bytes\n /// @return leaf hash\n function hashLeaf(bytes memory _key, bytes memory _value) public pure returns (bytes32) {\n return keccak256(abi.encodePacked(_key, _value));\n }\n\n /// @dev verifies, if provided key-value pair was part of consensus\n /// @param _blockId consensus ID for which we doing a check\n /// @param _proof merkle proof for pair\n /// @param _key pair key\n /// @param _value pair value\n /// @return TRUE if key-value par was part of consensus, FALSE otherwise\n function verifyProofForBlock(\n uint256 _blockId,\n bytes32[] memory _proof,\n bytes memory _key,\n bytes memory _value\n )\n public\n view\n returns (bool)\n {\n return _proof.verify(roots[_blockId], keccak256(abi.encodePacked(_key, _value)));\n }\n\n /// @dev this is helper method, that extracts one merkle proof from many hashed provided as bytes\n /// @param _data many hashes as bytes\n /// @param _offset this is starting point for extraction\n /// @param _items how many hashes to extract\n /// @return merkle proof (array of bytes32 hashes)\n function bytesToBytes32Array(\n bytes memory _data,\n uint256 _offset,\n uint256 _items\n )\n public\n pure\n returns (bytes32[] memory)\n {\n bytes32[] memory dataList = new bytes32[](_items);\n\n // we can unchecked because we working only with `i` and `_offset`\n // in case of wrong `_offset` it will throw\n unchecked {\n for (uint256 i = 0; i < _items; i++) {\n bytes32 temp;\n uint256 idx = (i + 1 + _offset) * 32;\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n temp := mload(add(_data, idx))\n }\n\n dataList[i] = temp;\n }\n }\n\n return (dataList);\n }\n\n /// @dev batch method for data verification\n /// @param _blockIds consensus IDs for which we doing a checks\n /// @param _proofs merkle proofs for all pair, sequence of hashes provided as bytes\n /// @param _proofItemsCounter array of counters, each counter tells how many hashes proof for each leaf has\n /// @param _leaves array of merkle leaves\n /// @return results array of verification results, TRUE if leaf is part of consensus, FALSE otherwise\n function verifyProofs(\n uint32[] memory _blockIds,\n bytes memory _proofs,\n uint256[] memory _proofItemsCounter,\n bytes32[] memory _leaves\n )\n public\n view\n returns (bool[] memory results)\n {\n results = new bool[](_leaves.length);\n uint256 offset = 0;\n\n for (uint256 i = 0; i < _leaves.length;) {\n results[i] = bytesToBytes32Array(_proofs, offset, _proofItemsCounter[i]).verify(\n roots[_blockIds[i]], _leaves[i]\n );\n\n unchecked {\n // we can uncheck because it will not overflow in a lifetime, and if someone provide invalid counter\n // we verification will not be valid (or we throw because of invalid memory access)\n offset += _proofItemsCounter[i];\n // we can uncheck because `i` will not overflow in a lifetime\n i++;\n }\n }\n }\n\n /// @param _blockId consensus ID\n /// @return root for provided consensus ID\n function getBlockRoot(uint32 _blockId) external view returns (bytes32) {\n return roots[_blockId];\n }\n\n /// @param _blockId consensus ID\n /// @return timestamp for provided consensus ID\n function getBlockTimestamp(uint32 _blockId) external view returns (uint32) {\n return roots[_blockId] == bytes32(0) ? 0 : _blockId;\n }\n\n /// @dev batch getter for FCDs\n /// @param _keys FCDs keys to fetch\n /// @return values array of FCDs values\n /// @return timestamps array of FCDs timestamps\n function getCurrentValues(bytes32[] calldata _keys)\n external\n view\n returns (uint256[] memory values, uint32[] memory timestamps)\n {\n timestamps = new uint32[](_keys.length);\n values = new uint256[](_keys.length);\n\n for (uint i=0; i<_keys.length;) {\n FirstClassData storage numericFCD = fcds[_keys[i]];\n values[i] = uint256(numericFCD.value);\n timestamps[i] = numericFCD.dataTimestamp;\n\n unchecked {\n // we can uncheck because `i` will not overflow in a lifetime\n i++;\n }\n }\n }\n\n /// @dev getter for single FCD value\n /// @param _key FCD key\n /// @return value FCD value\n /// @return timestamp FCD timestamp\n function getCurrentValue(bytes32 _key) external view returns (uint256 value, uint256 timestamp) {\n FirstClassData storage numericFCD = fcds[_key];\n return (uint256(numericFCD.value), numericFCD.dataTimestamp);\n }\n\n /// @dev getter for single FCD value in case its type is `int`\n /// @param _key FCD key\n /// @return value FCD value\n /// @return timestamp FCD timestamp\n function getCurrentIntValue(bytes32 _key) external view returns (int256 value, uint256 timestamp) {\n FirstClassData storage numericFCD = fcds[_key];\n return (numericFCD.value.toInt(), numericFCD.dataTimestamp);\n }\n\n function _setPadding(uint32 _padding) internal onlyOwner {\n if (_consensusData.padding == _padding) revert NoChangeToState();\n\n _consensusData.padding = _padding;\n emit LogPadding(msg.sender, _padding);\n }\n\n /// @dev we cloning last block time, because we will need reference point for next submissions\n function _cloneLastDataFromPrevChain(address _prevChain) internal {\n (bool success, bytes memory v) = _prevChain.staticcall(abi.encode(_VERSION_SELECTOR));\n uint256 prevVersion = success ? abi.decode(v, (uint256)) : 1;\n\n if (prevVersion == 1) {\n uint32 latestId = IBaseChainV1(address(_prevChain)).getLatestBlockId();\n _consensusData.lastTimestamp = IBaseChainV1(address(_prevChain)).getBlockTimestamp(latestId);\n\n // +1 because getLatestBlockId subtracts 1\n // +1 because it might be situation when tx is already in progress in old contract\n // and old contract do not have deprecated flag\n _consensusData.sequence = latestId + 2;\n _consensusData.blocksCountOffset = latestId + 2;\n } else { // VERSION 2\n // with new Registry, we have register/unregister methods\n // Chain will be deprecated, so there is no need to do \"+1\" as in old version\n // TODO what with current Registries??\n // we need a way to make it deprecated!\n ConsensusData memory data = BaseChain(_prevChain).getConsensusData();\n\n _consensusData.sequence = data.sequence;\n _consensusData.blocksCountOffset = data.sequence;\n _consensusData.lastTimestamp = data.lastTimestamp;\n }\n }\n}\n" + }, + "contracts/Chain.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./BaseChain.sol\";\n\ncontract Chain is BaseChain {\n IStakingBank public immutable stakingBank;\n\n event LogMint(address indexed minter, uint256 blockId, uint256 staked, uint256 power);\n event LogVoter(uint256 indexed blockId, address indexed voter, uint256 vote);\n\n error NotEnoughSignatures();\n error SignaturesOutOfOrder();\n\n /// @param _contractRegistry Registry address\n /// @param _padding required \"space\" between blocks in seconds\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n /// @param _allowForMixedType we have two \"types\" of Chain: HomeChain and ForeignChain, when we redeploying\n /// we don't want to mix up them, so we checking, if new Chain has the same type as current one.\n /// However, when we will be switching from one homechain to another one, we have to allow for this mixing up.\n /// This flag will tell contract, if this is the case.\n constructor(\n IRegistry _contractRegistry,\n uint32 _padding,\n uint16 _requiredSignatures,\n bool _allowForMixedType\n ) BaseChain(_contractRegistry, _padding, _requiredSignatures, _allowForMixedType) {\n stakingBank = IStakingBank(_contractRegistry.requireAndGetAddress(\"StakingBank\"));\n }\n\n /// @dev method for submitting consensus data\n /// @param _dataTimestamp consensus timestamp, this is time for all data in merkle tree including FCDs\n /// @param _root merkle root\n /// @param _keys FCDs keys\n /// @param _values FCDs values\n /// @param _v array of `v` part of validators signatures\n /// @param _r array of `r` part of validators signatures\n /// @param _s array of `s` part of validators signatures\n // solhint-disable-next-line function-max-lines, code-complexity\n function submit(\n uint32 _dataTimestamp,\n bytes32 _root,\n bytes32[] memory _keys,\n uint256[] memory _values,\n uint8[] memory _v,\n bytes32[] memory _r,\n bytes32[] memory _s\n ) external {\n // below two checks are only for pretty errors, so we can safe gas and allow for raw revert\n // if (_keys.length != _values.length) revert ArraysDataDoNotMatch();\n // if (_v.length != _r.length || _r.length != _s.length) revert ArraysDataDoNotMatch();\n\n _verifySubmitTimestampAndIncSequence(_dataTimestamp);\n\n // we can't expect minter will have exactly the same timestamp\n // but for sure we can demand not to be off by a lot, that's why +3sec\n // temporary remove this condition, because recently on ropsten we see cases when minter/node\n // can be even 100sec behind\n // require(_dataTimestamp <= block.timestamp + 3,\n // string(abi.encodePacked(\"oh, so you can predict the future:\", _dataTimestamp - block.timestamp + 48)));\n\n bytes memory testimony = abi.encodePacked(_dataTimestamp, _root);\n\n for (uint256 i = 0; i < _keys.length;) {\n if (uint224(_values[i]) != _values[i]) revert FCDOverflow();\n\n fcds[_keys[i]] = FirstClassData(uint224(_values[i]), _dataTimestamp);\n testimony = abi.encodePacked(testimony, _keys[i], _values[i]);\n\n unchecked {\n // we can't pass enough data to overflow\n i++;\n }\n }\n\n uint256 signatures = 0;\n uint256 power = 0;\n //uint256 staked = stakingBank.totalSupply();\n bytes32 affidavit = keccak256(testimony);\n\n address prevSigner = address(0x0);\n\n for (uint256 i; i < _v.length;) {\n address signer = recoverSigner(affidavit, _v[i], _r[i], _s[i]);\n uint256 balance = stakingBank.balanceOf(signer);\n\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\n\n prevSigner = signer;\n\n if (balance == 0) {\n unchecked { i++; }\n continue;\n }\n\n signatures++;\n emit LogVoter(uint256(_dataTimestamp), signer, balance);\n\n unchecked {\n // we can't overflow because that means token overflowed\n // and even if we do, we will get lower power\n power += balance;\n i++;\n }\n }\n\n if (signatures < _REQUIRED_SIGNATURES) revert NotEnoughSignatures();\n\n emit LogMint(msg.sender, _dataTimestamp, stakingBank.totalSupply(), power);\n\n // TODO remember to protect against flash loans when DPoS will be in place\n // we turn on power once we have DPoS in action, we have PoA now\n // require(power * 100 / staked >= 66, \"not enough power was gathered\");\n\n roots[_dataTimestamp] = _root;\n _consensusData.lastTimestamp = _dataTimestamp;\n }\n\n /// @inheritdoc BaseChain\n function isForeign() external pure virtual override returns (bool) {\n return false;\n }\n\n /// @dev helper method that returns all important data about current state of contract\n /// @return blockNumber `block.number`\n /// @return timePadding `this.padding`\n /// @return lastDataTimestamp timestamp for last submitted consensus\n /// @return lastId ID of last submitted consensus\n /// @return nextLeader leader for `block.timestamp + 1`\n /// @return nextBlockId block ID for `block.timestamp + padding`\n /// @return validators array of all validators addresses\n /// @return powers array of all validators powers\n /// @return locations array of all validators locations\n /// @return staked total UMB staked by validators\n /// @return minSignatures `this.requiredSignatures`\n function getStatus() external view virtual returns(\n uint256 blockNumber,\n uint32 timePadding,\n uint32 lastDataTimestamp,\n uint32 lastId,\n address nextLeader,\n uint32 nextBlockId,\n address[] memory validators,\n uint256[] memory powers,\n string[] memory locations,\n uint256 staked,\n uint16 minSignatures\n ) {\n ConsensusData memory data = _consensusData;\n\n blockNumber = block.number;\n timePadding = data.padding;\n lastId = data.lastTimestamp;\n lastDataTimestamp = lastId;\n minSignatures = _REQUIRED_SIGNATURES;\n\n staked = stakingBank.totalSupply();\n uint256 numberOfValidators = stakingBank.getNumberOfValidators();\n powers = new uint256[](numberOfValidators);\n validators = new address[](numberOfValidators);\n locations = new string[](numberOfValidators);\n\n for (uint256 i = 0; i < numberOfValidators;) {\n validators[i] = stakingBank.addresses(i);\n (, locations[i]) = stakingBank.validators(validators[i]);\n powers[i] = stakingBank.balanceOf(validators[i]);\n\n unchecked {\n // we will run out of gas before overflow happen\n i++;\n }\n }\n\n unchecked {\n // we will not overflow with timestamp in a lifetime\n nextBlockId = lastId + data.padding + 1;\n\n nextLeader = numberOfValidators > 0\n // we will not overflow with timestamp in a lifetime\n ? validators[getLeaderIndex(numberOfValidators, block.timestamp + 1)]\n : address(0);\n }\n }\n\n /// @return address of leader for next second\n function getNextLeaderAddress() external view returns (address) {\n return getLeaderAddressAtTime(block.timestamp + 1);\n }\n\n /// @return address of current leader\n function getLeaderAddress() external view returns (address) {\n return getLeaderAddressAtTime(block.timestamp);\n }\n\n /// @param _numberOfValidators total number of validators\n /// @param _timestamp timestamp for which you want to calculate index\n /// @return leader index, use it for StakingBank.addresses[index] to fetch leader address\n function getLeaderIndex(uint256 _numberOfValidators, uint256 _timestamp) public view virtual returns (uint256) {\n ConsensusData memory data = _consensusData;\n\n unchecked {\n // we will not overflow on `timestamp` and `padding` in a life time\n // timePadding + 1 => because padding is a space between blocks,\n // so next round starts on first block after padding\n // TODO will it work for off-chain??\n uint256 validatorIndex = data.sequence + (_timestamp - data.lastTimestamp) / (data.padding + 1);\n\n return validatorIndex % _numberOfValidators;\n }\n }\n\n // @todo - properly handled non-enabled validators, newly added validators, and validators with low stake\n /// @param _timestamp timestamp for which you want to calculate leader address\n /// @return leader address for provider timestamp\n function getLeaderAddressAtTime(uint256 _timestamp) public view virtual returns (address) {\n uint256 numberOfValidators = stakingBank.getNumberOfValidators();\n\n if (numberOfValidators == 0) {\n return address(0x0);\n }\n\n uint256 validatorIndex = getLeaderIndex(numberOfValidators, _timestamp);\n\n return stakingBank.addresses(validatorIndex);\n }\n\n /// @dev we had stack too deep in `submit` so this method was created as a solution\n // we increasing `_consensusData.sequence` here so we don't have to read sequence again in other place\n function _verifySubmitTimestampAndIncSequence(uint256 _dataTimestamp) internal {\n ConsensusData memory data = _consensusData;\n\n // `data.lastTimestamp` must be setup either on deployment\n // or via cloning from previous contract\n if (data.lastTimestamp == 0) revert ContractNotReady();\n\n unchecked {\n // we will not overflow with timestamp and padding in a life time\n if (data.lastTimestamp + data.padding >= _dataTimestamp) revert BlockSubmittedToFastOrDataToOld();\n }\n\n unchecked {\n // we will not overflow in a life time\n _consensusData.sequence = uint32(data.sequence + 1);\n }\n }\n}\n" + }, + "contracts/extensions/Registrable.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\n/// @dev Any contract that we want to register in ContractRegistry, must inherit from Registrable\nabstract contract Registrable {\n IRegistry public immutable contractRegistry;\n\n modifier onlyFromContract(address _msgSender, bytes32 _contractName) {\n require(\n contractRegistry.getAddress(_contractName) == _msgSender,\n string(abi.encodePacked(\"caller is not \", _contractName))\n );\n _;\n }\n\n modifier withRegistrySetUp() {\n require(address(contractRegistry) != address(0x0), \"_registry is empty\");\n _;\n }\n\n constructor(IRegistry _contractRegistry) {\n require(address(_contractRegistry) != address(0x0), \"_registry is empty\");\n contractRegistry = _contractRegistry;\n }\n\n /// @dev this method will be called as a first method in registration process when old contract will be replaced\n /// when called, old contract address is still in registry\n function register() virtual external;\n\n /// @dev this method will be called as a last method in registration process when old contract will be replaced\n /// when called, new contract address is already in registry\n function unregister() virtual external;\n\n /// @return contract name as bytes32\n function getName() virtual external pure returns (bytes32);\n\n /// @dev helper method for fetching StakingBank address\n function stakingBankContract() public view returns (IStakingBank) {\n return IStakingBank(contractRegistry.requireAndGetAddress(\"StakingBank\"));\n }\n\n /// @dev helper method for fetching UMB address\n function tokenContract() public view withRegistrySetUp returns (ERC20) {\n return ERC20(contractRegistry.requireAndGetAddress(\"UMB\"));\n }\n}\n" + }, + "contracts/ForeignChain.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./Chain.sol\";\n\n/// @dev contract for foreign chains\ncontract ForeignChain is Chain {\n error NotSupported();\n\n /// @param _contractRegistry Registry address\n /// @param _padding required \"space\" between blocks in seconds\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n constructor(\n IRegistry _contractRegistry,\n uint32 _padding,\n uint16 _requiredSignatures,\n bool _allowForMixedType\n ) Chain(_contractRegistry, _padding, _requiredSignatures, _allowForMixedType) {\n // no additional configuration needed\n }\n\n /// @inheritdoc BaseChain\n function isForeign() external pure override returns (bool) {\n return true;\n }\n\n /// @inheritdoc Chain\n /// @notice this method is made to be compatible with MasterChain, but it does not return full data eg validators\n /// data will be missing.\n /// @return blockNumber `block.number`\n /// @return timePadding `this.padding`\n /// @return lastDataTimestamp timestamp for last submitted consensus\n /// @return lastId ID of last submitted consensus\n /// @return nextLeader will be always address(0)\n /// @return nextBlockId block ID for `block.timestamp + padding`\n /// @return validators array will be always empty\n /// @return powers array will be always empty\n /// @return locations array will be always empty\n /// @return staked total UMB staked by validators\n /// @return minSignatures `this.requiredSignatures`\n function getStatus() external view override returns(\n uint256 blockNumber,\n uint32 timePadding,\n uint32 lastDataTimestamp,\n uint32 lastId,\n address nextLeader,\n uint32 nextBlockId,\n address[] memory validators,\n uint256[] memory powers,\n string[] memory locations,\n uint256 staked,\n uint16 minSignatures\n ) {\n ConsensusData memory data = _consensusData;\n\n blockNumber = block.number;\n timePadding = data.padding;\n lastId = data.lastTimestamp;\n lastDataTimestamp = lastId;\n minSignatures = _REQUIRED_SIGNATURES;\n\n staked = stakingBank.totalSupply();\n uint256 numberOfValidators = 0;\n powers = new uint256[](numberOfValidators);\n validators = new address[](numberOfValidators);\n locations = new string[](numberOfValidators);\n nextLeader = address(0);\n\n unchecked {\n // we will not overflow with timestamp in a lifetime\n nextBlockId = lastId + data.padding + 1;\n }\n }\n\n function getLeaderIndex(uint256, uint256) public pure override returns (uint256) {\n revert NotSupported();\n }\n\n function getLeaderAddressAtTime(uint256) public pure override returns (address) {\n revert NotSupported();\n }\n}\n" + }, + "contracts/interfaces/IBaseChainV1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IBaseChainV1 {\n /// @dev number of blocks (consensus rounds) saved in this contract\n function blocksCount() external returns (uint32);\n\n /// @dev number of all blocks that were generated before switching to this contract\n /// please note, that there might be a gap of one block when we switching from old to new contract\n /// see constructor for details\n function blocksCountOffset() external returns (uint32);\n\n function getLatestBlockId() external view returns (uint32);\n\n function getBlockTimestamp(uint32 _blockId) external view returns (uint32);\n\n function getStatus() external view returns (\n uint256 blockNumber,\n uint16 timePadding,\n uint32 lastDataTimestamp,\n uint32 lastId,\n uint32 nextBlockId\n );\n}\n" + }, + "contracts/interfaces/IRegistry.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\n\ninterface IRegistry {\n event LogRegistered(address indexed destination, bytes32 name);\n\n /// @dev imports new contract addresses and override old addresses, if they exist under provided name\n /// This method can be used for contracts that for some reason do not have `getName` method\n /// @param _names array of contract names that we want to register\n /// @param _destinations array of contract addresses\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external;\n\n /// @dev imports new contracts and override old addresses, if they exist.\n /// Names of contracts are fetched directly from each contract by calling `getName`\n /// @param _destinations array of contract addresses\n function importContracts(address[] calldata _destinations) external;\n\n /// @dev this method ensure, that old and new contract is aware of it state in registry\n /// Note: BSC registry does not have this method. This method was introduced in later stage.\n /// @param _newContract address of contract that will replace old one\n function atomicUpdate(address _newContract) external;\n\n /// @dev similar to `getAddress` but throws when contract name not exists\n /// @param name contract name\n /// @return contract address registered under provided name or throws, if does not exists\n function requireAndGetAddress(bytes32 name) external view returns (address);\n\n /// @param name contract name in a form of bytes32\n /// @return contract address registered under provided name\n function getAddress(bytes32 name) external view returns (address);\n\n /// @param _name contract name\n /// @return contract address assigned to the name or address(0) if not exists\n function getAddressByString(string memory _name) external view returns (address);\n\n /// @dev helper method that converts string to bytes32,\n /// you can use to to generate contract name\n function stringToBytes32(string memory _string) external pure returns (bytes32 result);\n}\n" + }, + "contracts/interfaces/IStakingBank.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IStakingBank is IERC20 {\n /// @param id address of validator wallet\n /// @param location URL of the validator API\n struct Validator {\n address id;\n string location;\n }\n\n event LogValidatorRegistered(address indexed id);\n event LogValidatorUpdated(address indexed id);\n event LogValidatorRemoved(address indexed id);\n event LogMinAmountForStake(uint256 minAmountForStake);\n\n /// @dev setter for `minAmountForStake`\n function setMinAmountForStake(uint256 _minAmountForStake) external;\n\n /// @dev allows to stake `token` by validators\n /// Validator needs to approve StakingBank beforehand\n /// @param _value amount of tokens to stake\n function stake(uint256 _value) external;\n\n /// @dev notification about approval from `_from` address on UMB token\n /// Staking bank will stake max approved amount from `_from` address\n /// @param _from address which approved token spend for IStakingBank\n function receiveApproval(address _from) external returns (bool success);\n\n /// @dev withdraws stake tokens\n /// it throws, when balance will be less than required minimum for stake\n /// to withdraw all use `exit`\n function withdraw(uint256 _value) external returns (bool success);\n\n /// @dev unstake and withdraw all tokens\n function exit() external returns (bool success);\n\n /// @dev creates (register) new validator\n /// @param _id validator address\n /// @param _location location URL of the validator API\n function create(address _id, string calldata _location) external;\n\n /// @dev removes validator\n /// @param _id validator wallet\n function remove(address _id) external;\n\n /// @dev updates validator location\n /// @param _id validator wallet\n /// @param _location new validator URL\n function update(address _id, string calldata _location) external;\n\n /// @return total number of registered validators (with and without balance)\n function getNumberOfValidators() external view returns (uint256);\n\n /// @dev gets validator address for provided index\n /// @param _ix index in array of list of all validators wallets\n function addresses(uint256 _ix) external view returns (address);\n\n /// @param _id address of validator\n /// @return id address of validator\n /// @return location URL of validator\n function validators(address _id) external view returns (address id, string memory location);\n}\n" + }, + "contracts/interfaces/IStakingBankStatic.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./IStakingBank.sol\";\n\n\ninterface IStakingBankStatic is IStakingBank {\n /// @param _validators array of validators addresses to verify\n /// @return TRUE when all validators are valid, FALSE otherwise\n function verifyValidators(address[] calldata _validators) external view returns (bool);\n}\n" + }, + "contracts/interfaces/IUmbrellaFeeds.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IUmbrellaFeeds {\n struct PriceData {\n /// @dev this is placeholder, that can be used for some additional data\n /// atm of creating this smart contract, it is only used as marker for removed data (when == type(uint8).max)\n uint8 data;\n /// @dev heartbeat: how often price data will be refreshed in case price stay flat\n uint24 heartbeat;\n /// @dev timestamp: price time, at this time validators run consensus\n uint32 timestamp;\n /// @dev price\n uint128 price;\n }\n\n struct Signature {\n uint8 v;\n bytes32 r;\n bytes32 s;\n }\n\n /// @dev method for submitting consensus data\n /// @param _priceKeys array of keys for `_priceDatas`\n /// @param _priceDatas PriceData signed by validators\n /// @param _signatures validators signatures\n function update(\n bytes32[] calldata _priceKeys,\n PriceData[] calldata _priceDatas,\n Signature[] calldata _signatures\n ) external;\n\n /// @dev it will return array of price datas for provided `_keys`\n /// In case ony of feed does not exist, fallback call will be executed for that feed.\n /// @notice If data for any key not exists, function will revert. Use `getManyPriceDataRaw` method if you don't\n /// want revert.\n /// @param _keys array of feed keys\n /// @return data PriceData array\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data);\n\n /// @dev same as getManyPriceData() but does not revert on empty data.\n /// @notice This method does no revert if some data does not exists.\n /// Check `data.timestamp` to see if price exist, if it is 0, then it does not exist.\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data);\n\n /// @dev this is main endpoint for reading feeds.\n /// In case timestamp is empty (that means there is no data), contract will revert.\n /// If you do not need whole data from `PriceData` struct, you can save some gas by using other view methods that\n /// returns just what you need.\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return data full PriceData struct\n function getPriceData(bytes32 _key) external view returns (PriceData memory data);\n\n /// @notice reader for mapping\n /// @param _key hash of feed name\n /// @return data full PriceData struct\n function prices(bytes32 _key) external view returns (PriceData memory data);\n\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return price\n function getPrice(bytes32 _key) external view returns (uint128 price);\n\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return price\n /// @return timestamp\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp);\n\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return price\n /// @return timestamp\n /// @return heartbeat\n function getPriceTimestampHeartbeat(bytes32 _key)\n external\n view\n returns (uint128 price, uint32 timestamp, uint24 heartbeat);\n\n /// @dev This method should be used only for Layer2 as it is more gas consuming than others views.\n /// @notice It does not revert on empty data.\n /// @param _name string feed name\n /// @return data PriceData\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data);\n\n /// @dev decimals for prices stored in this contract\n function DECIMALS() external view returns (uint8); // solhint-disable-line func-name-mixedcase\n}\n" + }, + "contracts/interfaces/StakingBankStaticNotSupported.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./IStakingBank.sol\";\n\nabstract contract StakingBankStaticNotSupported is IStakingBank {\n error NotSupported();\n\n function create(address, string calldata) external pure {\n revert NotSupported();\n }\n\n function update(address, string calldata) external pure {\n revert NotSupported();\n }\n\n function remove(address) external pure {\n revert NotSupported();\n }\n\n function transfer(address, uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function transferFrom(address, address, uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function receiveApproval(address) external pure returns (bool) {\n revert NotSupported();\n }\n\n function allowance(address, address) external pure returns (uint256) {\n revert NotSupported();\n }\n\n function approve(address, uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function stake(uint256) external pure {\n revert NotSupported();\n }\n\n function withdraw(uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function exit() external pure returns (bool) {\n revert NotSupported();\n }\n\n function setMinAmountForStake(uint256) external pure {\n revert NotSupported();\n }\n}\n" + }, + "contracts/mock/Distributor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport \"../Registry.sol\";\n\ncontract Distributor is Ownable {\n address[] public recipients;\n uint256 public bottomLimit = 5e17;\n uint256 public topLimit = 1e18;\n\n constructor(address[] memory _recipients) {\n recipients = _recipients;\n }\n\n receive() external payable {\n distribute();\n }\n\n function setLimits(uint256 _bottom, uint256 _top) external onlyOwner {\n bottomLimit = _bottom;\n topLimit = _top;\n }\n\n function withdraw() external {\n uint balance = address(this).balance;\n uint buffer = recipients.length * (topLimit - bottomLimit);\n\n if (balance > buffer) {\n payable(owner()).transfer(balance - buffer);\n }\n }\n\n function addRecipients(address[] calldata _recipients) external onlyOwner {\n for (uint256 i = 0; i < _recipients.length; i++) {\n recipients.push(_recipients[i]);\n }\n }\n\n function removeRecipient(address _recipient) external onlyOwner {\n for (uint256 i = 0; i < recipients.length; i++) {\n if (recipients[i] == _recipient) {\n recipients[i] = recipients[recipients.length - 1];\n recipients.pop();\n return;\n }\n }\n }\n\n function recipientsCount() external view returns (uint256) {\n return recipients.length;\n }\n\n function allRecipients() external view returns (address[] memory) {\n return recipients;\n }\n\n function getName() external pure returns (bytes32) {\n return \"Distributor\";\n }\n\n function distribute() public {\n uint256 limit = bottomLimit;\n uint256 top = topLimit;\n uint256 count = recipients.length;\n uint256 totalBalance = address(this).balance;\n\n for (uint256 i = 0; i < count; i++) {\n uint256 balance = recipients[i].balance;\n\n if (balance > limit) {\n continue;\n }\n\n uint256 amount = top - balance > totalBalance ? totalBalance : top - balance;\n\n if (amount > 0) {\n payable(recipients[i]).transfer(amount);\n totalBalance -= amount;\n }\n }\n }\n}\n" + }, + "contracts/mock/LimitedMintingToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\ncontract LimitedMintingToken is ERC20, Ownable {\n struct MintData {\n uint256 dailyAllowance;\n mapping (address => uint256) lastMintTimestamp;\n mapping (address => uint256) todaysMintedAmount;\n }\n\n MintData public mintData;\n\n constructor(string memory _name, string memory _symbol, uint256 _dailyAllowance) ERC20(_name, _symbol) {\n mintData.dailyAllowance = _dailyAllowance;\n }\n\n function mint(address _holder, uint256 _amount) external {\n MintData storage data = mintData;\n\n (uint256 limit, bool fullLimit) = _currentLimit(data);\n\n require(limit > 0, \"This address already claimed the maximum daily amount\");\n\n uint256 lastTimestamp = data.lastMintTimestamp[msg.sender];\n uint256 mintedAmount = data.todaysMintedAmount[msg.sender];\n\n uint256 amount = _amount > limit ? limit : _amount;\n data.lastMintTimestamp[msg.sender] = fullLimit ? block.timestamp : lastTimestamp;\n data.todaysMintedAmount[msg.sender] = fullLimit ? amount : mintedAmount + amount;\n\n _mint(_holder, amount);\n }\n\n function mintApproveAndStake(IStakingBank _stakingBank, address _holder, uint256 _amount) external {\n _mint(_holder, _amount);\n _approve(_holder, address(_stakingBank), _amount);\n _stakingBank.receiveApproval(_holder);\n }\n\n function getDailyAllowance() external view returns (uint256) {\n return mintData.dailyAllowance;\n }\n\n function getName() external pure returns (bytes32) {\n return \"UMB\";\n }\n\n function setDailyAllowance(uint256 newDailyAllowance) public onlyOwner {\n MintData storage data = mintData;\n data.dailyAllowance = newDailyAllowance;\n }\n\n function _currentLimit(MintData storage data) internal view returns (uint256 limit, bool fullLimit) {\n uint256 lastMint = data.lastMintTimestamp[msg.sender];\n fullLimit = block.timestamp - lastMint >= 24 hours;\n\n uint256 usedLimit = data.todaysMintedAmount[msg.sender];\n\n limit = fullLimit ? data.dailyAllowance : data.dailyAllowance - usedLimit;\n }\n}\n" + }, + "contracts/mock/Token.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\n// please remember this is our dummy token!\n// it will be replaced by proper DPoS solution in future\ncontract Token is ERC20 {\n constructor(\n string memory _name,\n string memory _symbol) ERC20(_name, _symbol) {\n }\n\n function mint(address _holder, uint256 _amount) external {\n _mint(_holder, _amount);\n }\n\n function mintApproveAndStake(IStakingBank _stakingBank, address _holder, uint256 _amount) external {\n _mint(_holder, _amount);\n _approve(_holder, address(_stakingBank), _amount);\n _stakingBank.receiveApproval(_holder);\n }\n\n function getName() external pure returns (bytes32) {\n return \"UMB\";\n }\n}\n" + }, + "contracts/onChainFeeds/UmbrellaFeeds.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/IUmbrellaFeeds.sol\";\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IStakingBankStatic.sol\";\n\n/// @dev Main contract for all on-chain data.\n/// Check `UmbrellaFeedsReader` to see how to integrate.\n///\n/// @notice This contract can be destroyed and replaced with new one (with new address).\n/// For best gas efficiency you should pick one of two ways of integration:\n/// 1. make `UmbrellaFeeds` immutable and use fallback in case of selfdestruct. After new deployment, it is recommended\n/// to update address to avoid fallback and reduce gas cost to minimum. In long run this is most efficient solution,\n/// better than any proxy.\n/// 2. always check newest `UmbrellaFeeds` via `Regostry` and fallback will not be needed.\ncontract UmbrellaFeeds is IUmbrellaFeeds {\n bytes constant public ETH_PREFIX = \"\\x19Ethereum Signed Message:\\n32\";\n string constant public NAME = \"UmbrellaFeeds\";\n\n /// @dev deployment time, used for protect for unintentional destroy\n uint256 public immutable DEPLOYED_AT; // solhint-disable-line var-name-mixedcase\n\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\n /// resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev StakingBank contract where list of validators is stored\n IStakingBankStatic public immutable STAKING_BANK; // solhint-disable-line var-name-mixedcase\n\n /// @dev minimal number of signatures required for accepting price submission (PoA)\n uint16 public immutable REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\n\n /// @dev decimals for prices stored in this contract\n uint8 public immutable DECIMALS; // solhint-disable-line var-name-mixedcase\n\n /// @notice map of all prices stored in this contract, key for map is hash of feed name\n /// eg for \"ETH-USD\" feed, key will be hash(\"ETH-USD\")\n mapping (bytes32 => PriceData) private _prices;\n\n error ArraysDataDoNotMatch();\n error FeedNotExist();\n error NotEnoughSignatures();\n error InvalidSigner();\n error InvalidRequiredSignatures();\n error SignaturesOutOfOrder();\n error ECDSAInvalidSignatureS();\n error ECDSAInvalidSignatureV();\n error OldData();\n error ContractInUse();\n error ContractNotInitialised();\n\n /// @param _contractRegistry Registry address\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n /// @param _decimals decimals for prices stored in this contract\n constructor(\n IRegistry _contractRegistry,\n uint16 _requiredSignatures,\n uint8 _decimals\n ) {\n if (_requiredSignatures == 0) revert InvalidRequiredSignatures();\n\n REGISTRY = _contractRegistry;\n REQUIRED_SIGNATURES = _requiredSignatures;\n STAKING_BANK = IStakingBankStatic(_contractRegistry.requireAndGetAddress(\"StakingBank\"));\n DECIMALS = _decimals;\n DEPLOYED_AT = block.timestamp;\n }\n\n /// @dev destroys old contract\n /// there is sanity check that prevents abuse of destroy method\n /// @param _name string feed key to verify, that contract was initialised\n function destroy(string calldata _name) external {\n if (REGISTRY.getAddressByString(NAME) == address(this)) revert ContractInUse();\n\n if (_prices[keccak256(abi.encodePacked(_name))].timestamp == 0 && DEPLOYED_AT + 3 days > block.timestamp) {\n revert ContractNotInitialised();\n }\n\n selfdestruct(payable(msg.sender));\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function update(\n bytes32[] calldata _priceKeys,\n PriceData[] calldata _priceDatas,\n Signature[] calldata _signatures\n ) external {\n if (_priceKeys.length != _priceDatas.length) revert ArraysDataDoNotMatch();\n\n bytes32 priceDataHash = keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n verifySignatures(priceDataHash, _signatures);\n\n uint256 i;\n\n while (i < _priceDatas.length) {\n bytes32 priceKey = _priceKeys[i];\n\n // we do not allow for older prices\n // at the same time it prevents from reusing signatures\n if (_prices[priceKey].timestamp >= _priceDatas[i].timestamp) revert OldData();\n\n _prices[priceKey] = _priceDatas[i];\n\n // atm there is no need for events, so in order to save gas, we do not emit any\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n if (data[i].timestamp == 0) revert FeedNotExist();\n\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function prices(bytes32 _key) external view returns (PriceData memory data) {\n data = _prices[_key];\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceData(bytes32 _key) external view returns (PriceData memory data) {\n data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPrice(bytes32 _key) external view returns (uint128 price) {\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return data.price;\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp) {\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp);\n }\n\n function getPriceTimestampHeartbeat(bytes32 _key)\n external\n view\n returns (uint128 price, uint32 timestamp, uint24 heartbeat)\n {\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp, data.heartbeat);\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data) {\n bytes32 key = keccak256(abi.encodePacked(_name));\n data = _prices[key];\n }\n\n /// @dev helper method for QA purposes\n /// @return hash of data that are signed by validators (keys and priced data)\n function hashData(bytes32[] calldata _priceKeys, PriceData[] calldata _priceDatas)\n external\n view\n returns (bytes32)\n {\n return keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n }\n\n /// @param _hash hash of signed data\n /// @param _signatures array of validators signatures\n function verifySignatures(bytes32 _hash, Signature[] calldata _signatures) public view {\n address prevSigner = address(0x0);\n\n if (_signatures.length < REQUIRED_SIGNATURES) revert NotEnoughSignatures();\n\n address[] memory validators = new address[](REQUIRED_SIGNATURES);\n\n // to save gas we check only required number of signatures\n // case, where you can have part of signatures invalid but still enough valid in total is not supported\n for (uint256 i; i < REQUIRED_SIGNATURES;) {\n (uint8 v, bytes32 r, bytes32 s) = (_signatures[i].v, _signatures[i].r, _signatures[i].s);\n\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n revert ECDSAInvalidSignatureS();\n }\n\n if (uint8(v) != 27 && uint8(v) != 28) revert ECDSAInvalidSignatureV();\n\n address signer = recoverSigner(_hash, v, r, s);\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\n\n // because we check only required number of signatures, any invalid one will cause revert\n prevSigner = signer;\n validators[i] = signer;\n\n unchecked { i++; }\n }\n\n // bulk verification can optimise gas when we have 5 or more validators\n if (!STAKING_BANK.verifyValidators(validators)) revert InvalidSigner();\n }\n\n function getChainId() public view returns (uint256 id) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n id := chainid()\n }\n }\n\n /// @param _hash hashed of data\n /// @param _v part of signature\n /// @param _r part of signature\n /// @param _s part of signature\n /// @return signer address\n function recoverSigner(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _hash));\n return ecrecover(hash, _v, _r, _s);\n }\n\n /// @dev to follow Registrable interface\n function getName() public pure returns (bytes32) {\n return \"UmbrellaFeeds\";\n }\n}\n" + }, + "contracts/onChainFeeds/UmbrellaFeedsReader.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IUmbrellaFeeds.sol\";\n\n/// @dev This is optional price reader for just one feed.\n/// It comes with chanilink interface that makes migration process easier.\n/// For maximum gas optimisation it is recommended to use UmbrellaFeeds directly - simply follow this contract as\n/// a guide for integration.\n///\n/// This contract has build in fallback feature in case, `UmbrellaFeeds` will be replaced by newer contract.\n/// Fallback is transparent for the user, no additional setup is needed.\n///\n/// How fallback feature works? If data for provided key is empty (when UmbrellaFeeds was destroyed and replaced),\n/// contract will execute following procedure:\n/// 1. if data is empty, contract will check if there is new registered contract with requested data\n/// 2. if data is found in new contract it will be returned\n/// 3. if there is no data or there is no new contract tx will revert.\ncontract UmbrellaFeedsReader {\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\n /// resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev contract where all the feeds are stored\n address public immutable UMBRELLA_FEEDS; // solhint-disable-line var-name-mixedcase\n\n /// @dev key (hash of string key), under which feed is being stored\n bytes32 public immutable KEY; // solhint-disable-line var-name-mixedcase\n\n /// @dev string representation of feed key (feed name)\n string public description;\n\n /// @dev decimals for feed\n uint8 internal immutable _DECIMALS; // solhint-disable-line var-name-mixedcase\n\n error EmptyAddress();\n error FeedNotExist();\n\n /// @param _registry IRegistry address\n /// @param _umbrellaFeeds UmbrellaFeeds address\n /// @param _key price data key (before hashing)\n constructor(IRegistry _registry, IUmbrellaFeeds _umbrellaFeeds, string memory _key) {\n if (address(_registry) == address(0)) revert EmptyAddress();\n\n REGISTRY = _registry;\n UMBRELLA_FEEDS = address(_umbrellaFeeds);\n description = _key;\n _DECIMALS = _umbrellaFeeds.DECIMALS();\n\n bytes32 hash = keccak256(abi.encodePacked(_key));\n KEY = hash;\n\n // sanity check\n _umbrellaFeeds.getPriceData(hash);\n }\n\n /// @dev decimals for feed\n function decimals() external view returns (uint8) {\n return _DECIMALS;\n }\n\n /// @dev this method follows chainlink interface for easy migration, NOTE: not all returned data are covered!\n /// latestRoundData() raise exception when there is no data, instead of returning unset values,\n /// which could be misinterpreted as actual reported values.\n /// It DOES NOT raise when data is outdated (based on heartbeat and timestamp).\n /// @notice You can save some gas by doing call directly to `UMBRELLA_FEEDS` contract.\n /// @return uint80 originally `roundId`, not in use, always 0\n /// @return answer price\n /// @return uint256 originally `startedAt`, not in use, always 0\n /// @return updatedAt last timestamp data was updated\n /// @return uint80 originally `answeredInRound` not in use, always 0\n function latestRoundData()\n external\n view\n returns (\n uint80 /* roundId */,\n int256 answer,\n uint256 /* startedAt */,\n uint256 updatedAt,\n uint80 /* answeredInRound */\n )\n {\n IUmbrellaFeeds.PriceData memory priceData = _getPriceDataRaw();\n\n if (priceData.timestamp == 0) {\n priceData = _fallbackCall();\n }\n\n return (0, int256(uint256(priceData.price)), 0, priceData.timestamp, 0);\n }\n\n /// @dev this is main endpoint for reading feed. Feed is read from UmbrellaFeeds contract using hardcoded `KEY`.\n /// In case timestamp is empty (that means there is no data), contract will execute fallback call.\n /// @notice revert on empty data\n function getPriceData() external view returns (IUmbrellaFeeds.PriceData memory priceData) {\n priceData = _getPriceDataRaw();\n\n if (priceData.timestamp == 0) {\n priceData = _fallbackCall();\n }\n }\n\n /// @dev same as `getPriceData` but does not revert when no data\n function getPriceDataRaw() external view returns (IUmbrellaFeeds.PriceData memory priceData) {\n priceData = _getPriceDataRaw();\n\n if (priceData.timestamp == 0) {\n return _fallbackCallRaw();\n }\n }\n\n /// @dev same as `getPriceData` but does not revert when no data\n function _getPriceDataRaw() internal view returns (IUmbrellaFeeds.PriceData memory priceData) {\n (bool success, bytes memory data) = UMBRELLA_FEEDS.staticcall(\n abi.encodeWithSelector(IUmbrellaFeeds.prices.selector, KEY)\n );\n\n if (success && data.length != 0) {\n priceData = abi.decode(data, (IUmbrellaFeeds.PriceData));\n }\n }\n\n /// @dev it will revert on empty data\n function _fallbackCall() internal view returns (IUmbrellaFeeds.PriceData memory data) {\n address umbrellaFeeds = REGISTRY.getAddressByString(\"UmbrellaFeeds\");\n\n // if contract was NOT updated, fallback is not needed, data does not exist - revert\n if (umbrellaFeeds == UMBRELLA_FEEDS) revert FeedNotExist();\n\n data = IUmbrellaFeeds(umbrellaFeeds).getPriceData(KEY);\n }\n\n /// @dev it will not revert on empty data\n function _fallbackCallRaw() internal view returns (IUmbrellaFeeds.PriceData memory data) {\n address umbrellaFeeds = REGISTRY.getAddressByString(\"UmbrellaFeeds\");\n\n // if contract was updated, we do fallback\n if (umbrellaFeeds != UMBRELLA_FEEDS) {\n data = IUmbrellaFeeds(umbrellaFeeds).prices(KEY);\n }\n }\n}\n" + }, + "contracts/onChainFeeds/UmbrellaFeedsReaderFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\nimport \"./UmbrellaFeedsReader.sol\";\n\n/// @notice Factory to deploy UmbrellaFeedsReader contract\ncontract UmbrellaFeedsReaderFactory {\n /// @dev Registry contract where list of all addresses is stored. Used to resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev list of all readers\n mapping (bytes32 => UmbrellaFeedsReader) public readers;\n\n event NewUmbrellaFeedsReader(UmbrellaFeedsReader indexed umbrellaFeedsReader, string feedName);\n\n error EmptyAddress();\n\n constructor(IRegistry _registry) {\n if (address(_registry) == address(0)) revert EmptyAddress();\n\n REGISTRY = _registry;\n }\n\n /// @dev Method to deploy new UmbrellaFeedsReader for particular key.\n /// This deployment is optional and it can be done by anyone who needs it.\n /// Reader can be used to simplify migration from Chainlink to Umbrella.\n ///\n /// Check UmbrellaFeedsReader docs for more details.\n ///\n /// We not using minimal proxy because it does not allow for immutable variables.\n /// @param _feedName string Feed name that is registered in UmbrellaFeeds\n /// @return reader UmbrellaFeedsReader contract address, in case anyone wants to use it from Layer1\n function deploy(string memory _feedName) external returns (UmbrellaFeedsReader reader) {\n reader = deployed(_feedName);\n IUmbrellaFeeds umbrellaFeeds = IUmbrellaFeeds(REGISTRY.getAddressByString(\"UmbrellaFeeds\"));\n\n // if UmbrellaFeeds contract is up to date, there is no need to redeploy\n if (address(reader) != address(0) && address(reader.UMBRELLA_FEEDS()) == address(umbrellaFeeds)) {\n return reader;\n }\n\n reader = new UmbrellaFeedsReader(REGISTRY, umbrellaFeeds, _feedName);\n readers[hash(_feedName)] = reader;\n\n emit NewUmbrellaFeedsReader(reader, _feedName);\n }\n\n function deployed(string memory _feedName) public view returns (UmbrellaFeedsReader) {\n return readers[hash(_feedName)];\n }\n\n function hash(string memory _feedName) public pure returns (bytes32) {\n return keccak256(abi.encodePacked(_feedName));\n }\n\n /// @dev to follow Registrable interface\n function getName() public pure returns (bytes32) {\n return \"UmbrellaFeedsReaderFactory\";\n }\n}\n" + }, + "contracts/onChainFeeds/zk-link/UmbrellaFeeds.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../../interfaces/IUmbrellaFeeds.sol\";\nimport \"../../interfaces/IRegistry.sol\";\nimport \"../../interfaces/IStakingBankStatic.sol\";\n\n/// @dev Main contract for all on-chain data.\n/// Check `UmbrellaFeedsReader` to see how to integrate.\n///\n/// @notice This contract can be destroyed and replaced with new one (with new address).\n/// For best gas efficiency you should pick one of two ways of integration:\n/// 1. make `UmbrellaFeeds` immutable and use fallback in case of selfdestruct. After new deployment, it is recommended\n/// to update address to avoid fallback and reduce gas cost to minimum. In long run this is most efficient solution,\n/// better than any proxy.\n/// 2. always check newest `UmbrellaFeeds` via `Regostry` and fallback will not be needed.\ncontract UmbrellaFeeds is IUmbrellaFeeds {\n bytes constant public ETH_PREFIX = \"\\x19Ethereum Signed Message:\\n32\";\n string constant public NAME = \"UmbrellaFeeds\";\n\n /// @dev deployment time, used for protect for unintentional destroy\n uint256 public immutable DEPLOYED_AT; // solhint-disable-line var-name-mixedcase\n\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\n /// resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev StakingBank contract where list of validators is stored\n IStakingBankStatic public immutable STAKING_BANK; // solhint-disable-line var-name-mixedcase\n\n /// @dev minimal number of signatures required for accepting price submission (PoA)\n uint16 public immutable REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\n\n /// @dev decimals for prices stored in this contract\n uint8 public immutable DECIMALS; // solhint-disable-line var-name-mixedcase\n\n /// @dev in case selfdestruct is not supported, this flag will make sure contract is not usable anymore\n bool public disabled;\n\n /// @notice map of all prices stored in this contract, key for map is hash of feed name\n /// eg for \"ETH-USD\" feed, key will be hash(\"ETH-USD\")\n mapping (bytes32 => PriceData) private _prices;\n\n error SelfDestruct();\n error ArraysDataDoNotMatch();\n error FeedNotExist();\n error NotEnoughSignatures();\n error InvalidSigner();\n error InvalidRequiredSignatures();\n error SignaturesOutOfOrder();\n error ECDSAInvalidSignatureS();\n error ECDSAInvalidSignatureV();\n error OldData();\n error ContractInUse();\n error ContractNotInitialised();\n\n /// @param _contractRegistry Registry address\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n /// @param _decimals decimals for prices stored in this contract\n constructor(\n IRegistry _contractRegistry,\n uint16 _requiredSignatures,\n uint8 _decimals\n ) {\n if (_requiredSignatures == 0) revert InvalidRequiredSignatures();\n\n REGISTRY = _contractRegistry;\n REQUIRED_SIGNATURES = _requiredSignatures;\n STAKING_BANK = IStakingBankStatic(_contractRegistry.requireAndGetAddress(\"StakingBank\"));\n DECIMALS = _decimals;\n DEPLOYED_AT = block.timestamp;\n }\n\n /// @dev destroys old contract\n /// there is sanity check that prevents abuse of destroy method\n /// @param _name string feed key to verify, that contract was initialised\n function destroy(string calldata _name) external {\n if (REGISTRY.getAddressByString(NAME) == address(this)) revert ContractInUse();\n\n if (_prices[keccak256(abi.encodePacked(_name))].timestamp == 0 && DEPLOYED_AT + 3 days > block.timestamp) {\n revert ContractNotInitialised();\n }\n\n disabled = true;\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function update(\n bytes32[] calldata _priceKeys,\n PriceData[] calldata _priceDatas,\n Signature[] calldata _signatures\n ) external {\n if (disabled) revert SelfDestruct();\n if (_priceKeys.length != _priceDatas.length) revert ArraysDataDoNotMatch();\n\n bytes32 priceDataHash = keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n verifySignatures(priceDataHash, _signatures);\n\n uint256 i;\n\n while (i < _priceDatas.length) {\n bytes32 priceKey = _priceKeys[i];\n\n // we do not allow for older prices\n // at the same time it prevents from reusing signatures\n if (_prices[priceKey].timestamp >= _priceDatas[i].timestamp) revert OldData();\n\n _prices[priceKey] = _priceDatas[i];\n\n // atm there is no need for events, so in order to save gas, we do not emit any\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n if (disabled) revert SelfDestruct();\n\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n if (data[i].timestamp == 0) revert FeedNotExist();\n\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n if (disabled) revert SelfDestruct();\n\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function prices(bytes32 _key) external view returns (PriceData memory data) {\n if (disabled) revert SelfDestruct();\n\n data = _prices[_key];\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceData(bytes32 _key) external view returns (PriceData memory data) {\n if (disabled) revert SelfDestruct();\n\n data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPrice(bytes32 _key) external view returns (uint128 price) {\n if (disabled) revert SelfDestruct();\n\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return data.price;\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp) {\n if (disabled) revert SelfDestruct();\n\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp);\n }\n\n function getPriceTimestampHeartbeat(bytes32 _key)\n external\n view\n returns (uint128 price, uint32 timestamp, uint24 heartbeat)\n {\n if (disabled) revert SelfDestruct();\n\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp, data.heartbeat);\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data) {\n if (disabled) revert SelfDestruct();\n\n bytes32 key = keccak256(abi.encodePacked(_name));\n data = _prices[key];\n }\n\n /// @dev helper method for QA purposes\n /// @return hash of data that are signed by validators (keys and priced data)\n function hashData(bytes32[] calldata _priceKeys, PriceData[] calldata _priceDatas)\n external\n view\n returns (bytes32)\n {\n return keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n }\n\n /// @param _hash hash of signed data\n /// @param _signatures array of validators signatures\n function verifySignatures(bytes32 _hash, Signature[] calldata _signatures) public view {\n address prevSigner = address(0x0);\n\n if (_signatures.length < REQUIRED_SIGNATURES) revert NotEnoughSignatures();\n\n address[] memory validators = new address[](REQUIRED_SIGNATURES);\n\n // to save gas we check only required number of signatures\n // case, where you can have part of signatures invalid but still enough valid in total is not supported\n for (uint256 i; i < REQUIRED_SIGNATURES;) {\n (uint8 v, bytes32 r, bytes32 s) = (_signatures[i].v, _signatures[i].r, _signatures[i].s);\n\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n revert ECDSAInvalidSignatureS();\n }\n\n if (uint8(v) != 27 && uint8(v) != 28) revert ECDSAInvalidSignatureV();\n\n address signer = recoverSigner(_hash, v, r, s);\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\n\n // because we check only required number of signatures, any invalid one will cause revert\n prevSigner = signer;\n validators[i] = signer;\n\n unchecked { i++; }\n }\n\n // bulk verification can optimise gas when we have 5 or more validators\n if (!STAKING_BANK.verifyValidators(validators)) revert InvalidSigner();\n }\n\n function getChainId() public view returns (uint256 id) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n id := chainid()\n }\n }\n\n /// @param _hash hashed of data\n /// @param _v part of signature\n /// @param _r part of signature\n /// @param _s part of signature\n /// @return signer address\n function recoverSigner(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _hash));\n return ecrecover(hash, _v, _r, _s);\n }\n\n /// @dev to follow Registrable interface\n function getName() public pure returns (bytes32) {\n return \"UmbrellaFeeds\";\n }\n}\n" + }, + "contracts/Registry.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\n// Inheritance\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport \"./extensions/Registrable.sol\";\nimport \"./interfaces/IRegistry.sol\";\n\n/// @dev contracts registry\n/// protocol uses this registry to fetch current contract addresses\ncontract Registry is IRegistry, Ownable {\n /// name => contract address\n mapping(bytes32 => address) public registry;\n\n\n error NameNotRegistered();\n error ArraysDataDoNotMatch();\n\n /// @inheritdoc IRegistry\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external onlyOwner {\n if (_names.length != _destinations.length) revert ArraysDataDoNotMatch();\n\n for (uint i = 0; i < _names.length;) {\n registry[_names[i]] = _destinations[i];\n emit LogRegistered(_destinations[i], _names[i]);\n\n unchecked {\n i++;\n }\n }\n }\n\n /// @inheritdoc IRegistry\n function importContracts(address[] calldata _destinations) external onlyOwner {\n for (uint i = 0; i < _destinations.length;) {\n bytes32 name = Registrable(_destinations[i]).getName();\n registry[name] = _destinations[i];\n emit LogRegistered(_destinations[i], name);\n\n unchecked {\n i++;\n }\n }\n }\n\n /// @inheritdoc IRegistry\n function atomicUpdate(address _newContract) external onlyOwner {\n Registrable(_newContract).register();\n\n bytes32 name = Registrable(_newContract).getName();\n address oldContract = registry[name];\n registry[name] = _newContract;\n\n Registrable(oldContract).unregister();\n\n emit LogRegistered(_newContract, name);\n }\n\n /// @inheritdoc IRegistry\n function requireAndGetAddress(bytes32 name) external view returns (address) {\n address _foundAddress = registry[name];\n if (_foundAddress == address(0)) revert NameNotRegistered();\n\n return _foundAddress;\n }\n\n /// @inheritdoc IRegistry\n function getAddress(bytes32 _bytes) external view returns (address) {\n return registry[_bytes];\n }\n\n /// @inheritdoc IRegistry\n function getAddressByString(string memory _name) public view returns (address) {\n return registry[stringToBytes32(_name)];\n }\n\n /// @inheritdoc IRegistry\n function stringToBytes32(string memory _string) public pure returns (bytes32 result) {\n bytes memory tempEmptyStringTest = bytes(_string);\n\n if (tempEmptyStringTest.length == 0) {\n return 0x0;\n }\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n result := mload(add(_string, 32))\n }\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStatic.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/StakingBankStaticNotSupported.sol\";\n\n/// @dev Because we are using PoA in UMB oracle, staked balance does not matter. What's matter is, if signer is\n/// validator or not. In this case we can optimise `StakingBank` and make it static for better gas performance.\nabstract contract StakingBankStatic is StakingBankStaticNotSupported {\n uint256 public constant ONE = 1e18;\n\n uint256 public immutable NUMBER_OF_VALIDATORS; // solhint-disable-line var-name-mixedcase\n uint256 public immutable TOTAL_SUPPLY; // solhint-disable-line var-name-mixedcase\n\n constructor(uint256 _validatorsCount) {\n NUMBER_OF_VALIDATORS = _validatorsCount;\n TOTAL_SUPPLY = _validatorsCount * ONE;\n\n _assertValidSetup(_validatorsCount);\n }\n\n function balances(address _validator) external view returns (uint256) {\n return _isValidator(_validator) ? ONE : 0;\n }\n\n function verifyValidators(address[] calldata _validators) external view returns (bool) {\n for (uint256 i; i < _validators.length;) {\n if (!_isValidator(_validators[i])) return false;\n unchecked { i++; }\n }\n\n return true;\n }\n\n function getNumberOfValidators() external view returns (uint256) {\n return NUMBER_OF_VALIDATORS;\n }\n\n function getAddresses() external view returns (address[] memory) {\n return _addresses();\n }\n\n function getBalances() external view returns (uint256[] memory allBalances) {\n allBalances = new uint256[](NUMBER_OF_VALIDATORS);\n\n for (uint256 i; i < NUMBER_OF_VALIDATORS;) {\n allBalances[i] = ONE;\n\n unchecked {\n // we will not have enough data to overflow\n i++;\n }\n }\n }\n\n function addresses(uint256 _ix) external view returns (address) {\n return _addresses()[_ix];\n }\n\n function validators(address _id) external view virtual returns (address id, string memory location);\n\n /// @dev to follow ERC20 interface\n function balanceOf(address _account) external view returns (uint256) {\n return _isValidator(_account) ? ONE : 0;\n }\n\n /// @dev to follow ERC20 interface\n function totalSupply() external view returns (uint256) {\n return TOTAL_SUPPLY;\n }\n\n /// @dev to follow Registrable interface\n function getName() external pure returns (bytes32) {\n return \"StakingBank\";\n }\n\n /// @dev to follow Registrable interface\n function register() external pure {\n // there are no requirements atm\n }\n\n /// @dev to follow Registrable interface\n function unregister() external pure {\n // there are no requirements atm\n }\n\n function _addresses() internal view virtual returns (address[] memory);\n\n function _isValidator(address _validator) internal view virtual returns (bool);\n\n function _assertValidSetup(uint256 _validatorsCount) internal view virtual{\n address[] memory list = _addresses();\n require(list.length == _validatorsCount);\n\n for (uint256 i; i < _validatorsCount;) {\n require(_isValidator(list[i]));\n\n unchecked { i ++; }\n }\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticCI.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticCI is StakingBankStatic {\n // 0x87630b2d1de0fbd5044eb6891b3d9d98c34c8d310c852f98550ba774480e47cc\n address public constant VALIDATOR_0 = 0x2fFd013AaA7B5a7DA93336C2251075202b33FB2B;\n // 0x3f1e8b94c70206bf816c1ed0b15ad98bdf225ae4c6e7e4eee6cdbcf706fda2ae\n address public constant VALIDATOR_1 = 0x43158ea338Ff13D0bDa0c3EB969B9EA5a624E7Cc;\n // 0x5da6b84117504d06b5dcd52b990d76965d2882f4e5852eb610bc76e4209b10d7\n address public constant VALIDATOR_2 = 0x9Fd8DD0627b9A32399Fd115c4725C7e17BC40e6d;\n // 0x1e5012671de3332ad0b43661984e94ab0e405bffddc9d3e863055040bab354b8\n address public constant VALIDATOR_3 = 0xa3F3659E469b7aE0b249546338DEdc0b684edB05;\n // 0x0edc1e35ea7701ddac703286674e79f04addbf5d2f6162fabc19d39bd3dc6662\n address public constant VALIDATOR_4 = 0xB98A954B9036DF144d685E910bfbAEC6B33A8d11;\n // 0x23c601ae397441f3ef6f1075dcb0031ff17fb079837beadaf3c84d96c6f3e569\n address public constant VALIDATOR_5 = 0xE5904695748fe4A84b40b3fc79De2277660BD1D3;\n\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.ci.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.ci.umb.network\");\n if (_id == VALIDATOR_2) return (_id, \"https://validator3.ci.umb.network\");\n if (_id == VALIDATOR_3) return (_id, \"https://validator4.ci.umb.network\");\n if (_id == VALIDATOR_4) return (_id, \"https://validator5.ci.umb.network\");\n if (_id == VALIDATOR_5) return (_id, \"https://validator6.ci.umb.network\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n list[2] = VALIDATOR_2;\n list[3] = VALIDATOR_3;\n list[4] = VALIDATOR_4;\n list[5] = VALIDATOR_5;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0\n || _validator == VALIDATOR_1\n || _validator == VALIDATOR_2\n || _validator == VALIDATOR_3\n || _validator == VALIDATOR_4\n || _validator == VALIDATOR_5\n );\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticDev.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticDev is StakingBankStatic {\n address public constant VALIDATOR_0 = 0xDc3eBc37DA53A644D67E5E3b5BA4EEF88D969d5C;\n address public constant VALIDATOR_1 = 0x998cb7821e605cC16b6174e7C50E19ADb2Dd2fB0;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.dev.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.dev.umb.network\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0 || _validator == VALIDATOR_1);\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticLocal.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticLocal is StakingBankStatic {\n address public constant VALIDATOR_0 = 0xeAD9C93b79Ae7C1591b1FB5323BD777E86e150d4;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"localhost\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0);\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticProd.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\ncontract StakingBankStaticProd is StakingBankStatic {\n address public constant VALIDATOR_0 = 0x977Ba523420110e230643B772Fe9cF955e11dA7B;\n address public constant VALIDATOR_1 = 0xe2422b23e52bc13ebA04d7FbB9F332Deb43360fB;\n\n // external order is based on validators submits on AVAX for Apr 2023\n address public constant VALIDATOR_2 = 0x57F404aD75e371c1A539589C1eFCA12e0C6980AD;\n address public constant VALIDATOR_3 = 0xD56C6A4f64E0bD70260472d1DB6Cf5825858CB0d;\n address public constant VALIDATOR_4 = 0x93FdcAB283b0BcAc48157590af482E1CFd6af6aC;\n address public constant VALIDATOR_5 = 0xCd733E06B06083d52fC5867E8E3432aA5c103A38;\n address public constant VALIDATOR_6 = 0x42e210b110c6aa49CdfA7ceF1444Aa4719653111;\n address public constant VALIDATOR_7 = 0x501731c6a69803a53Ec6c3e12f293c247cE1092B;\n address public constant VALIDATOR_8 = 0x8bF9661F1b247522C75DD0FE84355aD2EfF27144;\n address public constant VALIDATOR_9 = 0x281754Ab58391A478B7aA4E7f39991CfB41118c4;\n address public constant VALIDATOR_10 = 0x57A51D5BDcE188c2295fCA3b4687475a54E65A02;\n address public constant VALIDATOR_11 = 0x2F85824B2B38F179E451988670935d315b5b9692;\n address public constant VALIDATOR_12 = 0xA7241994267682de4dE7Ef62f52dc2C783d1784B;\n address public constant VALIDATOR_13 = 0x6eEd457C20603EDAE50C3A112CAA1a9425321bD0;\n address public constant VALIDATOR_14 = 0xC5a7650c2725a7B6A39f15cb9FbffC7af357AFeb;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n // solhint-disable-next-line code-complexity\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.umb.network\");\n if (_id == VALIDATOR_2) return (_id, \"https://umbrella.artemahr.tech\");\n if (_id == VALIDATOR_3) return (_id, \"https://umb.vtabsolutions.com:3030\");\n if (_id == VALIDATOR_4) return (_id, \"https://umbrella.crazywhale.es\");\n if (_id == VALIDATOR_5) return (_id, \"https://umbrella-node.gateomega.com\");\n if (_id == VALIDATOR_6) return (_id, \"https://umb.anorak.technology\");\n if (_id == VALIDATOR_7) return (_id, \"https://umbrella.validator.infstones.io\");\n if (_id == VALIDATOR_8) return (_id, \"https://umb.hashkey.cloud\");\n if (_id == VALIDATOR_9) return (_id, \"http://umbrella.staking4all.org:3000\");\n if (_id == VALIDATOR_10) return (_id, \"http://5.161.78.230:3000\");\n if (_id == VALIDATOR_11) return (_id, \"https://umb-api.staking.rocks\");\n if (_id == VALIDATOR_12) return (_id, \"https://rpc.urbanhq.net\");\n if (_id == VALIDATOR_13) return (_id, \"https://umbrella-node.ankastake.com\");\n if (_id == VALIDATOR_14) return (_id, \"https://umbrella.tchambrella.com\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n list[2] = VALIDATOR_2;\n list[3] = VALIDATOR_3;\n list[4] = VALIDATOR_4;\n list[5] = VALIDATOR_5;\n list[6] = VALIDATOR_6;\n list[7] = VALIDATOR_7;\n list[8] = VALIDATOR_8;\n list[9] = VALIDATOR_9;\n list[10] = VALIDATOR_10;\n list[11] = VALIDATOR_11;\n list[12] = VALIDATOR_12;\n list[13] = VALIDATOR_13;\n list[14] = VALIDATOR_14;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (\n _validator == VALIDATOR_0\n || _validator == VALIDATOR_1\n || _validator == VALIDATOR_2\n || _validator == VALIDATOR_3\n || _validator == VALIDATOR_4\n || _validator == VALIDATOR_5\n || _validator == VALIDATOR_6\n || _validator == VALIDATOR_7\n || _validator == VALIDATOR_8\n || _validator == VALIDATOR_9\n || _validator == VALIDATOR_10\n || _validator == VALIDATOR_11\n || _validator == VALIDATOR_12\n || _validator == VALIDATOR_13\n || _validator == VALIDATOR_14\n );\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticSbx.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticSbx is StakingBankStatic {\n address public constant VALIDATOR_0 = 0xE3bDa0C6E1fBB111091Dfef6f22a673b20Ea5F50;\n address public constant VALIDATOR_1 = 0xc1773490F00963CBAb3841fc07C1a0796E658Ba2;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.sbx.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.sbx.umb.network\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0 || _validator == VALIDATOR_1);\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": false, + "runs": 0 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/rootstock_production/StakingBankStatic.json b/deployments/rootstock_production/StakingBankStatic.json index 05fb8432..3820b320 100644 --- a/deployments/rootstock_production/StakingBankStatic.json +++ b/deployments/rootstock_production/StakingBankStatic.json @@ -1,5 +1,5 @@ { - "address": "0x6fC13EACE26590B80cCCAB1ba5d51890577D83B2", + "address": "0xff38197cceF56149976C6D7F6103eB700C086247", "abi": [ { "inputs": [ @@ -249,58 +249,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "VALIDATOR_15", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATOR_16", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATOR_17", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATOR_18", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "VALIDATOR_2", @@ -812,30 +760,30 @@ "type": "function" } ], - "transactionHash": "0xc9ee62b1f54409fafa897808d5663497ef677e8d5bf7f06c7cd20490934397a2", + "transactionHash": "0x697a3a9da1345af36b24a9137306e8b68666b1c68d1aa8cd4cf916f19ea9af07", "receipt": { "to": null, "from": "0xA6e4fFa19B213AbeA258ae72e8e1a209B9E543e7", - "contractAddress": "0x6fC13EACE26590B80cCCAB1ba5d51890577D83B2", - "transactionIndex": 2, - "gasUsed": "2643132", + "contractAddress": "0xff38197cceF56149976C6D7F6103eB700C086247", + "transactionIndex": 5, + "gasUsed": "2300821", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x6389a76709a5f66df54b412e8e7182c10cec172070cc050b768a431622e6c8d0", - "transactionHash": "0xc9ee62b1f54409fafa897808d5663497ef677e8d5bf7f06c7cd20490934397a2", + "blockHash": "0x7b0488d17bfdf94dd2f66666de1e8c6f4740a61de98ff1ed9056fef04f8424fa", + "transactionHash": "0x697a3a9da1345af36b24a9137306e8b68666b1c68d1aa8cd4cf916f19ea9af07", "logs": [], - "blockNumber": 6227920, - "cumulativeGasUsed": "2756437", + "blockNumber": 6854373, + "cumulativeGasUsed": "2589683", "status": 1, "byzantium": true }, "args": [ - 19 + 15 ], - "numDeployments": 1, - "solcInputHash": "4db3e1d3dd51dbe508dc0a6a04352df6", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_validatorsCount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"NotSupported\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"minAmountForStake\",\"type\":\"uint256\"}],\"name\":\"LogMinAmountForStake\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"NUMBER_OF_VALIDATORS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ONE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TOTAL_SUPPLY\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_0\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_1\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_10\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_11\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_12\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_13\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_14\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_15\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_16\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_17\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_18\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_2\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_3\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_4\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_5\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_6\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_7\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_8\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_9\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_ix\",\"type\":\"uint256\"}],\"name\":\"addresses\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validator\",\"type\":\"address\"}],\"name\":\"balances\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"create\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"exit\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBalances\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"allBalances\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumberOfValidators\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"receiveApproval\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"register\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"remove\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"setMinAmountForStake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"stake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"update\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_id\",\"type\":\"address\"}],\"name\":\"validators\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"location\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_validators\",\"type\":\"address[]\"}],\"name\":\"verifyValidators\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addresses(uint256)\":{\"details\":\"gets validator address for provided index\",\"params\":{\"_ix\":\"index in array of list of all validators wallets\"}},\"balanceOf(address)\":{\"details\":\"to follow ERC20 interface\"},\"exit()\":{\"details\":\"unstake and withdraw all tokens\"},\"getName()\":{\"details\":\"to follow Registrable interface\"},\"getNumberOfValidators()\":{\"returns\":{\"_0\":\"total number of registered validators (with and without balance)\"}},\"register()\":{\"details\":\"to follow Registrable interface\"},\"totalSupply()\":{\"details\":\"to follow ERC20 interface\"},\"unregister()\":{\"details\":\"to follow Registrable interface\"},\"validators(address)\":{\"params\":{\"_id\":\"address of validator\"},\"returns\":{\"id\":\"address of validator\",\"location\":\"URL of validator\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":\"StakingBankStaticProd\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":0},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBank.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IStakingBank is IERC20 {\\n /// @param id address of validator wallet\\n /// @param location URL of the validator API\\n struct Validator {\\n address id;\\n string location;\\n }\\n\\n event LogValidatorRegistered(address indexed id);\\n event LogValidatorUpdated(address indexed id);\\n event LogValidatorRemoved(address indexed id);\\n event LogMinAmountForStake(uint256 minAmountForStake);\\n\\n /// @dev setter for `minAmountForStake`\\n function setMinAmountForStake(uint256 _minAmountForStake) external;\\n\\n /// @dev allows to stake `token` by validators\\n /// Validator needs to approve StakingBank beforehand\\n /// @param _value amount of tokens to stake\\n function stake(uint256 _value) external;\\n\\n /// @dev notification about approval from `_from` address on UMB token\\n /// Staking bank will stake max approved amount from `_from` address\\n /// @param _from address which approved token spend for IStakingBank\\n function receiveApproval(address _from) external returns (bool success);\\n\\n /// @dev withdraws stake tokens\\n /// it throws, when balance will be less than required minimum for stake\\n /// to withdraw all use `exit`\\n function withdraw(uint256 _value) external returns (bool success);\\n\\n /// @dev unstake and withdraw all tokens\\n function exit() external returns (bool success);\\n\\n /// @dev creates (register) new validator\\n /// @param _id validator address\\n /// @param _location location URL of the validator API\\n function create(address _id, string calldata _location) external;\\n\\n /// @dev removes validator\\n /// @param _id validator wallet\\n function remove(address _id) external;\\n\\n /// @dev updates validator location\\n /// @param _id validator wallet\\n /// @param _location new validator URL\\n function update(address _id, string calldata _location) external;\\n\\n /// @return total number of registered validators (with and without balance)\\n function getNumberOfValidators() external view returns (uint256);\\n\\n /// @dev gets validator address for provided index\\n /// @param _ix index in array of list of all validators wallets\\n function addresses(uint256 _ix) external view returns (address);\\n\\n /// @param _id address of validator\\n /// @return id address of validator\\n /// @return location URL of validator\\n function validators(address _id) external view returns (address id, string memory location);\\n}\\n\",\"keccak256\":\"0x2c518aeab8b0b3a364fafaec559d3ff0dc6a119f8d203fa31ef7ad667ca0f7b9\",\"license\":\"MIT\"},\"contracts/interfaces/StakingBankStaticNotSupported.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./IStakingBank.sol\\\";\\n\\nabstract contract StakingBankStaticNotSupported is IStakingBank {\\n error NotSupported();\\n\\n function create(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function update(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function remove(address) external pure {\\n revert NotSupported();\\n }\\n\\n function transfer(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function transferFrom(address, address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function receiveApproval(address) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function allowance(address, address) external pure returns (uint256) {\\n revert NotSupported();\\n }\\n\\n function approve(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function stake(uint256) external pure {\\n revert NotSupported();\\n }\\n\\n function withdraw(uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function exit() external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function setMinAmountForStake(uint256) external pure {\\n revert NotSupported();\\n }\\n}\\n\",\"keccak256\":\"0xa899ad9000220b04bc3f63f762a9a6a76dcc09449427e7774a53f4ceda9c1cf8\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStatic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"../interfaces/StakingBankStaticNotSupported.sol\\\";\\n\\n/// @dev Because we are using PoA in UMB oracle, staked balance does not matter. What's matter is, if signer is\\n/// validator or not. In this case we can optimise `StakingBank` and make it static for better gas performance.\\nabstract contract StakingBankStatic is StakingBankStaticNotSupported {\\n uint256 public constant ONE = 1e18;\\n\\n uint256 public immutable NUMBER_OF_VALIDATORS; // solhint-disable-line var-name-mixedcase\\n uint256 public immutable TOTAL_SUPPLY; // solhint-disable-line var-name-mixedcase\\n\\n constructor(uint256 _validatorsCount) {\\n NUMBER_OF_VALIDATORS = _validatorsCount;\\n TOTAL_SUPPLY = _validatorsCount * ONE;\\n\\n _assertValidSetup(_validatorsCount);\\n }\\n\\n function balances(address _validator) external view returns (uint256) {\\n return _isValidator(_validator) ? ONE : 0;\\n }\\n\\n function verifyValidators(address[] calldata _validators) external view returns (bool) {\\n for (uint256 i; i < _validators.length;) {\\n if (!_isValidator(_validators[i])) return false;\\n unchecked { i++; }\\n }\\n\\n return true;\\n }\\n\\n function getNumberOfValidators() external view returns (uint256) {\\n return NUMBER_OF_VALIDATORS;\\n }\\n\\n function getAddresses() external view returns (address[] memory) {\\n return _addresses();\\n }\\n\\n function getBalances() external view returns (uint256[] memory allBalances) {\\n allBalances = new uint256[](NUMBER_OF_VALIDATORS);\\n\\n for (uint256 i; i < NUMBER_OF_VALIDATORS;) {\\n allBalances[i] = ONE;\\n\\n unchecked {\\n // we will not have enough data to overflow\\n i++;\\n }\\n }\\n }\\n\\n function addresses(uint256 _ix) external view returns (address) {\\n return _addresses()[_ix];\\n }\\n\\n function validators(address _id) external view virtual returns (address id, string memory location);\\n\\n /// @dev to follow ERC20 interface\\n function balanceOf(address _account) external view returns (uint256) {\\n return _isValidator(_account) ? ONE : 0;\\n }\\n\\n /// @dev to follow ERC20 interface\\n function totalSupply() external view returns (uint256) {\\n return TOTAL_SUPPLY;\\n }\\n\\n /// @dev to follow Registrable interface\\n function getName() external pure returns (bytes32) {\\n return \\\"StakingBank\\\";\\n }\\n\\n /// @dev to follow Registrable interface\\n function register() external pure {\\n // there are no requirements atm\\n }\\n\\n /// @dev to follow Registrable interface\\n function unregister() external pure {\\n // there are no requirements atm\\n }\\n\\n function _addresses() internal view virtual returns (address[] memory);\\n\\n function _isValidator(address _validator) internal view virtual returns (bool);\\n\\n function _assertValidSetup(uint256 _validatorsCount) internal view virtual{\\n address[] memory list = _addresses();\\n require(list.length == _validatorsCount);\\n\\n for (uint256 i; i < _validatorsCount;) {\\n require(_isValidator(list[i]));\\n\\n unchecked { i ++; }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfcc53ff98b0f1c42e1bc7345a1535fdc4e938ef40d323600ead94b2ece59a381\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./StakingBankStatic.sol\\\";\\n\\ncontract StakingBankStaticProd is StakingBankStatic {\\n address public constant VALIDATOR_0 = 0x977Ba523420110e230643B772Fe9cF955e11dA7B;\\n address public constant VALIDATOR_1 = 0xe2422b23e52bc13ebA04d7FbB9F332Deb43360fB;\\n\\n // external order is based on validators submits on AVAX for Apr 2023\\n address public constant VALIDATOR_2 = 0x57F404aD75e371c1A539589C1eFCA12e0C6980AD;\\n address public constant VALIDATOR_3 = 0xD56C6A4f64E0bD70260472d1DB6Cf5825858CB0d;\\n address public constant VALIDATOR_4 = 0x220230Eda8f50067Dd9e4729345dabCCe0C61542;\\n address public constant VALIDATOR_5 = 0x93FdcAB283b0BcAc48157590af482E1CFd6af6aC;\\n address public constant VALIDATOR_6 = 0xCd733E06B06083d52fC5867E8E3432aA5c103A38;\\n address public constant VALIDATOR_7 = 0x42e210b110c6aa49CdfA7ceF1444Aa4719653111;\\n address public constant VALIDATOR_8 = 0x501731c6a69803a53Ec6c3e12f293c247cE1092B;\\n address public constant VALIDATOR_9 = 0x8bF9661F1b247522C75DD0FE84355aD2EfF27144;\\n address public constant VALIDATOR_10 = 0x281754Ab58391A478B7aA4E7f39991CfB41118c4;\\n address public constant VALIDATOR_11 = 0xB9C63a350A04d8BD245d18928a26EE036352dDd8;\\n address public constant VALIDATOR_12 = 0x57A51D5BDcE188c2295fCA3b4687475a54E65A02;\\n address public constant VALIDATOR_13 = 0x777FbA3666fa7747476a34577FcCC404b263E09F;\\n address public constant VALIDATOR_14 = 0x2F85824B2B38F179E451988670935d315b5b9692;\\n address public constant VALIDATOR_15 = 0xA7241994267682de4dE7Ef62f52dc2C783d1784B;\\n address public constant VALIDATOR_16 = 0x6eEd457C20603EDAE50C3A112CAA1a9425321bD0;\\n address public constant VALIDATOR_17 = 0xC5a7650c2725a7B6A39f15cb9FbffC7af357AFeb;\\n address public constant VALIDATOR_18 = 0xFEd95453678920c1b7b3A81F033Ca02a27225556;\\n\\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\\n\\n // solhint-disable-next-line code-complexity\\n function validators(address _id) external pure override returns (address id, string memory location) {\\n if (_id == VALIDATOR_0) return (_id, \\\"https://validator.umb.network\\\");\\n if (_id == VALIDATOR_1) return (_id, \\\"https://validator2.umb.network\\\");\\n if (_id == VALIDATOR_2) return (_id, \\\"https://umbrella.artemahr.tech\\\");\\n if (_id == VALIDATOR_3) return (_id, \\\"https://umb.vtabsolutions.com:3030\\\");\\n if (_id == VALIDATOR_4) return (_id, \\\"https://umb.stakers.world\\\");\\n if (_id == VALIDATOR_5) return (_id, \\\"https://umbrella.crazywhale.es\\\");\\n if (_id == VALIDATOR_6) return (_id, \\\"https://umbrella-node.gateomega.com\\\");\\n if (_id == VALIDATOR_7) return (_id, \\\"https://umb.anorak.technology\\\");\\n if (_id == VALIDATOR_8) return (_id, \\\"https://umbrella.validator.infstones.io\\\");\\n if (_id == VALIDATOR_9) return (_id, \\\"https://umb.hashquark.io\\\");\\n if (_id == VALIDATOR_10) return (_id, \\\"http://umbrella.staking4all.org:3000\\\");\\n if (_id == VALIDATOR_11) return (_id, \\\"https://umbrella-api.validatrium.club\\\");\\n if (_id == VALIDATOR_12) return (_id, \\\"http://5.161.78.230:3000\\\");\\n if (_id == VALIDATOR_13) return (_id, \\\"https://umbnode.blockchainliverpool.com\\\");\\n if (_id == VALIDATOR_14) return (_id, \\\"https://umb-api.staking.rocks\\\");\\n if (_id == VALIDATOR_15) return (_id, \\\"https://rpc.urbanhq.net\\\");\\n if (_id == VALIDATOR_16) return (_id, \\\"https://umbrella-node.ankastake.com\\\");\\n if (_id == VALIDATOR_17) return (_id, \\\"https://umbrella.tchambrella.com\\\");\\n if (_id == VALIDATOR_18) return (_id, \\\"https://umbrella-node.cmt13.eu\\\");\\n\\n return (address(0), \\\"\\\");\\n }\\n\\n function _addresses() internal view override returns (address[] memory) {\\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\\n\\n list[0] = VALIDATOR_0;\\n list[1] = VALIDATOR_1;\\n list[2] = VALIDATOR_2;\\n list[3] = VALIDATOR_3;\\n list[4] = VALIDATOR_4;\\n list[5] = VALIDATOR_5;\\n list[6] = VALIDATOR_6;\\n list[7] = VALIDATOR_7;\\n list[8] = VALIDATOR_8;\\n list[9] = VALIDATOR_9;\\n list[10] = VALIDATOR_10;\\n list[11] = VALIDATOR_11;\\n list[12] = VALIDATOR_12;\\n list[13] = VALIDATOR_13;\\n list[14] = VALIDATOR_14;\\n list[15] = VALIDATOR_15;\\n list[16] = VALIDATOR_16;\\n list[17] = VALIDATOR_17;\\n list[18] = VALIDATOR_18;\\n\\n return list;\\n }\\n\\n function _isValidator(address _validator) internal pure override returns (bool) {\\n return (\\n _validator == VALIDATOR_0\\n || _validator == VALIDATOR_1\\n || _validator == VALIDATOR_2\\n || _validator == VALIDATOR_3\\n || _validator == VALIDATOR_4\\n || _validator == VALIDATOR_5\\n || _validator == VALIDATOR_6\\n || _validator == VALIDATOR_7\\n || _validator == VALIDATOR_8\\n || _validator == VALIDATOR_9\\n || _validator == VALIDATOR_10\\n || _validator == VALIDATOR_11\\n || _validator == VALIDATOR_12\\n || _validator == VALIDATOR_13\\n || _validator == VALIDATOR_14\\n || _validator == VALIDATOR_15\\n || _validator == VALIDATOR_16\\n || _validator == VALIDATOR_17\\n || _validator == VALIDATOR_18\\n );\\n }\\n}\\n\",\"keccak256\":\"0x1e80a063f381fdb75109238bd1e4db75af37b5aea8d8165293aee4bf84838c85\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60c06040523480156200001157600080fd5b5060405162003da238038062003da2833981810160405281019062000037919062000eaf565b808060808181525050670de0b6b3a76400008162000056919062000f10565b60a081815250506200006e816200007660201b60201c565b505062000fcf565b600062000088620000ef60201b60201c565b9050818151146200009857600080fd5b60005b82811015620000ea57620000d2828281518110620000be57620000bd62000f71565b5b6020026020010151620008dd60201b60201c565b620000dc57600080fd5b80806001019150506200009b565b505050565b6060600060805167ffffffffffffffff81111562000112576200011162000fa0565b5b604051908082528060200260200182016040528015620001415781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b8160008151811062000170576200016f62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110620001d657620001d562000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad816002815181106200023c576200023b62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110620002a257620002a162000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073220230eda8f50067dd9e4729345dabcce0c615428160048151811062000308576200030762000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac816005815181106200036e576200036d62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a3881600681518110620003d457620003d362000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa4719653111816007815181106200043a576200043962000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b81600881518110620004a0576200049f62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff271448160098151811062000506576200050562000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600a815181106200056c576200056b62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073b9c63a350a04d8bd245d18928a26ee036352ddd881600b81518110620005d257620005d162000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600c8151811062000638576200063762000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073777fba3666fa7747476a34577fccc404b263e09f81600d815181106200069e576200069d62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600e8151811062000704576200070362000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600f815181106200076a576200076962000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081601081518110620007d057620007cf62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb8160118151811062000836576200083562000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073fed95453678920c1b7b3a81f033ca02a27225556816012815181106200089c576200089b62000f71565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806200096d575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80620009b857507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a03575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a4e575073220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a9957507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ae4575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b2f57507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b7a575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000bc55750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000c10575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000c5b575073b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ca657507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000cf1575073777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000d3c5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000d87575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000dd25750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000e1d575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000e68575073fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b600080fd5b6000819050919050565b62000e898162000e74565b811462000e9557600080fd5b50565b60008151905062000ea98162000e7e565b92915050565b60006020828403121562000ec85762000ec762000e6f565b5b600062000ed88482850162000e98565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600062000f1d8262000e74565b915062000f2a8362000e74565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161562000f665762000f6562000ee1565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60805160a051612d8a62001018600039600081816109ac0152610c2e01526000818161081b0152818161088901528181610c5401528181610dbd0152611db40152612d8a6000f3fe608060405234801561001057600080fd5b50600436106102195760003560e01c8062113e081461021e578063015f7ed61461023c57806303a1e2241461025a578063095ea7b3146102785780630db18e37146102a857806317d7de7c146102d857806318160ddd146102f65780631aa3a008146103145780631d4f9ce01461031e57806323b872dd1461034e57806327e235e31461037e57806329092d0e146103ae5780632e1a7d4d146103ca578063398b056e146103fa578063411ff4971461041857806345f9f8251461043657806352b41e351461045457806354755335146104705780635dc4bfd31461048e57806361a3e37e146104ac57806369dc7ae4146104ca57806370a08231146104e8578063838e7c3a14610518578063902d55a5146105345780639031d9131461055257806390ff7e2e14610570578063952c4f181461058e578063989b6996146105ac5780639f0e9484146105ca578063a15ab08d146105e8578063a39fac1214610604578063a694fc3a14610622578063a9059cbb1461063e578063b2119eac1461066e578063b49b08421461068c578063c2ee3a08146106aa578063db731777146106c8578063dd62ed3e146106e6578063e214a5fc14610716578063e29349d614610734578063e2dc7a1a14610752578063e79a198f14610770578063e985e0081461077a578063e9fad8ee14610798578063edf26d9b146107b6578063fa52c7d8146107e6575b600080fd5b610226610817565b6040516102339190612645565b60405180910390f35b6102446108e8565b60405161025191906126a8565b60405180910390f35b610262610900565b60405161026f91906126a8565b60405180910390f35b610292600480360381019061028d9190612725565b610918565b60405161029f9190612780565b60405180910390f35b6102c260048036038101906102bd919061279b565b61094c565b6040516102cf9190612780565b60405180910390f35b6102e0610980565b6040516102ed91906127e1565b60405180910390f35b6102fe6109a8565b60405161030b919061280b565b60405180910390f35b61031c6109d0565b005b6103386004803603810190610333919061288b565b6109d2565b6040516103459190612780565b60405180910390f35b610368600480360381019061036391906128d8565b610a38565b6040516103759190612780565b60405180910390f35b6103986004803603810190610393919061279b565b610a6c565b6040516103a5919061280b565b60405180910390f35b6103c860048036038101906103c3919061279b565b610a93565b005b6103e460048036038101906103df919061292b565b610ac5565b6040516103f19190612780565b60405180910390f35b610402610af9565b60405161040f91906126a8565b60405180910390f35b610420610b11565b60405161042d91906126a8565b60405180910390f35b61043e610b29565b60405161044b91906126a8565b60405180910390f35b61046e6004803603810190610469919061292b565b610b41565b005b610478610b73565b60405161048591906126a8565b60405180910390f35b610496610b8b565b6040516104a391906126a8565b60405180910390f35b6104b4610ba3565b6040516104c191906126a8565b60405180910390f35b6104d2610bbb565b6040516104df91906126a8565b60405180910390f35b61050260048036038101906104fd919061279b565b610bd3565b60405161050f919061280b565b60405180910390f35b610532600480360381019061052d91906129ae565b610bfa565b005b61053c610c2c565b604051610549919061280b565b60405180910390f35b61055a610c50565b604051610567919061280b565b60405180910390f35b610578610c78565b60405161058591906126a8565b60405180910390f35b610596610c90565b6040516105a391906126a8565b60405180910390f35b6105b4610ca8565b6040516105c191906126a8565b60405180910390f35b6105d2610cc0565b6040516105df91906126a8565b60405180910390f35b61060260048036038101906105fd91906129ae565b610cd8565b005b61060c610d0a565b6040516106199190612acc565b60405180910390f35b61063c6004803603810190610637919061292b565b610d19565b005b61065860048036038101906106539190612725565b610d4b565b6040516106659190612780565b60405180910390f35b610676610d7f565b60405161068391906126a8565b60405180910390f35b610694610d97565b6040516106a191906126a8565b60405180910390f35b6106b2610daf565b6040516106bf919061280b565b60405180910390f35b6106d0610dbb565b6040516106dd919061280b565b60405180910390f35b61070060048036038101906106fb9190612aee565b610ddf565b60405161070d919061280b565b60405180910390f35b61071e610e13565b60405161072b91906126a8565b60405180910390f35b61073c610e2b565b60405161074991906126a8565b60405180910390f35b61075a610e43565b60405161076791906126a8565b60405180910390f35b610778610e5b565b005b610782610e5d565b60405161078f91906126a8565b60405180910390f35b6107a0610e75565b6040516107ad9190612780565b60405180910390f35b6107d060048036038101906107cb919061292b565b610ea9565b6040516107dd91906126a8565b60405180910390f35b61080060048036038101906107fb919061279b565b610ed4565b60405161080e929190612bc7565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff81111561085357610852612bf7565b5b6040519080825280602002602001820160405280156108815781602001602082028036833780820191505090505b50905060005b7f00000000000000000000000000000000000000000000000000000000000000008110156108e457670de0b6b3a76400008282815181106108cb576108ca612c26565b5b6020026020010181815250508080600101915050610887565b5090565b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b83839050811015610a2c57610a118484838181106109f7576109f6612c26565b5b9050602002016020810190610a0c919061279b565b61182e565b610a1f576000915050610a32565b80806001019150506109d6565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a778261182e565b610a82576000610a8c565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b732f85824b2b38f179e451988670935d315b5b969281565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b73fed95453678920c1b7b3a81f033ca02a2722555681565b73777fba3666fa7747476a34577fccc404b263e09f81565b6000610bde8261182e565b610be9576000610bf3565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b73220230eda8f50067dd9e4729345dabcce0c6154281565b73a7241994267682de4de7ef62f52dc2c783d1784b81565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610d14611dae565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73281754ab58391a478b7aa4e7f39991cfb41118c481565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b736eed457c20603edae50c3a112caa1a9425321bd081565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b565b73b9c63a350a04d8bd245d18928a26ee036352ddd881565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610eb3611dae565b8281518110610ec557610ec4612c26565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f5f57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611829565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fe657826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611829565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361106d57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611829565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110d75782604051806060016040528060228152602001612c796022913991509150611829565b73220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361115e57826040518060400160405280601981526020017f68747470733a2f2f756d622e7374616b6572732e776f726c640000000000000081525091509150611829565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111e557826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611829565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361124f5782604051806060016040528060238152602001612c566023913991509150611829565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112d657826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611829565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113405782604051806060016040528060278152602001612cbf6027913991509150611829565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113c757826040518060400160405280601881526020017f68747470733a2f2f756d622e68617368717561726b2e696f000000000000000081525091509150611829565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114315782604051806060016040528060248152602001612c9b6024913991509150611829565b73b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361149b5782604051806060016040528060258152602001612ce66025913991509150611829565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152257826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611829565b73777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361158c5782604051806060016040528060278152602001612d2e6027913991509150611829565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361161357826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611829565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361169a57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611829565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036117045782604051806060016040528060238152602001612d0b6023913991509150611829565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361178b57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611829565b73fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361181257826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612d6e6f64652e636d7431332e6575000081525091509150611829565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806118bd575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061190757507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611951575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061199b575073220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806119e557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a2f575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a7957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ac3575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b0d5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b57575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ba1575073b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611beb57507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c35575073777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c7f5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611cc9575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d135750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d5d575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611da7575073fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff811115611dec57611deb612bf7565b5b604051908082528060200260200182016040528015611e1a5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611e4657611e45612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611ea957611ea8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611f0c57611f0b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611f6f57611f6e612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073220230eda8f50067dd9e4729345dabcce0c6154281600481518110611fd257611fd1612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac8160058151811061203557612034612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a388160068151811061209857612097612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa4719653111816007815181106120fb576120fa612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b8160088151811061215e5761215d612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff27144816009815181106121c1576121c0612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600a8151811061222457612223612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073b9c63a350a04d8bd245d18928a26ee036352ddd881600b8151811061228757612286612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600c815181106122ea576122e9612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073777fba3666fa7747476a34577fccc404b263e09f81600d8151811061234d5761234c612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600e815181106123b0576123af612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600f8151811061241357612412612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd08160108151811061247657612475612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb816011815181106124d9576124d8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073fed95453678920c1b7b3a81f033ca02a272255568160128151811061253c5761253b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6125bc816125a9565b82525050565b60006125ce83836125b3565b60208301905092915050565b6000602082019050919050565b60006125f28261257d565b6125fc8185612588565b935061260783612599565b8060005b8381101561263857815161261f88826125c2565b975061262a836125da565b92505060018101905061260b565b5085935050505092915050565b6000602082019050818103600083015261265f81846125e7565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061269282612667565b9050919050565b6126a281612687565b82525050565b60006020820190506126bd6000830184612699565b92915050565b600080fd5b600080fd5b6126d681612687565b81146126e157600080fd5b50565b6000813590506126f3816126cd565b92915050565b612702816125a9565b811461270d57600080fd5b50565b60008135905061271f816126f9565b92915050565b6000806040838503121561273c5761273b6126c3565b5b600061274a858286016126e4565b925050602061275b85828601612710565b9150509250929050565b60008115159050919050565b61277a81612765565b82525050565b60006020820190506127956000830184612771565b92915050565b6000602082840312156127b1576127b06126c3565b5b60006127bf848285016126e4565b91505092915050565b6000819050919050565b6127db816127c8565b82525050565b60006020820190506127f660008301846127d2565b92915050565b612805816125a9565b82525050565b600060208201905061282060008301846127fc565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261284b5761284a612826565b5b8235905067ffffffffffffffff8111156128685761286761282b565b5b60208301915083602082028301111561288457612883612830565b5b9250929050565b600080602083850312156128a2576128a16126c3565b5b600083013567ffffffffffffffff8111156128c0576128bf6126c8565b5b6128cc85828601612835565b92509250509250929050565b6000806000606084860312156128f1576128f06126c3565b5b60006128ff868287016126e4565b9350506020612910868287016126e4565b925050604061292186828701612710565b9150509250925092565b600060208284031215612941576129406126c3565b5b600061294f84828501612710565b91505092915050565b60008083601f84011261296e5761296d612826565b5b8235905067ffffffffffffffff81111561298b5761298a61282b565b5b6020830191508360018202830111156129a7576129a6612830565b5b9250929050565b6000806000604084860312156129c7576129c66126c3565b5b60006129d5868287016126e4565b935050602084013567ffffffffffffffff8111156129f6576129f56126c8565b5b612a0286828701612958565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b612a4381612687565b82525050565b6000612a558383612a3a565b60208301905092915050565b6000602082019050919050565b6000612a7982612a0e565b612a838185612a19565b9350612a8e83612a2a565b8060005b83811015612abf578151612aa68882612a49565b9750612ab183612a61565b925050600181019050612a92565b5085935050505092915050565b60006020820190508181036000830152612ae68184612a6e565b905092915050565b60008060408385031215612b0557612b046126c3565b5b6000612b13858286016126e4565b9250506020612b24858286016126e4565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612b68578082015181840152602081019050612b4d565b83811115612b77576000848401525b50505050565b6000601f19601f8301169050919050565b6000612b9982612b2e565b612ba38185612b39565b9350612bb3818560208601612b4a565b612bbc81612b7d565b840191505092915050565b6000604082019050612bdc6000830185612699565b8181036020830152612bee8184612b8e565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6170692e76616c696461747269756d2e636c756268747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6d68747470733a2f2f756d626e6f64652e626c6f636b636861696e6c69766572706f6f6c2e636f6da26469706673582212209a1752a9ea487818b8a4d658f151da9487c0cc92638142159bacde7ec2d21f7564736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102195760003560e01c8062113e081461021e578063015f7ed61461023c57806303a1e2241461025a578063095ea7b3146102785780630db18e37146102a857806317d7de7c146102d857806318160ddd146102f65780631aa3a008146103145780631d4f9ce01461031e57806323b872dd1461034e57806327e235e31461037e57806329092d0e146103ae5780632e1a7d4d146103ca578063398b056e146103fa578063411ff4971461041857806345f9f8251461043657806352b41e351461045457806354755335146104705780635dc4bfd31461048e57806361a3e37e146104ac57806369dc7ae4146104ca57806370a08231146104e8578063838e7c3a14610518578063902d55a5146105345780639031d9131461055257806390ff7e2e14610570578063952c4f181461058e578063989b6996146105ac5780639f0e9484146105ca578063a15ab08d146105e8578063a39fac1214610604578063a694fc3a14610622578063a9059cbb1461063e578063b2119eac1461066e578063b49b08421461068c578063c2ee3a08146106aa578063db731777146106c8578063dd62ed3e146106e6578063e214a5fc14610716578063e29349d614610734578063e2dc7a1a14610752578063e79a198f14610770578063e985e0081461077a578063e9fad8ee14610798578063edf26d9b146107b6578063fa52c7d8146107e6575b600080fd5b610226610817565b6040516102339190612645565b60405180910390f35b6102446108e8565b60405161025191906126a8565b60405180910390f35b610262610900565b60405161026f91906126a8565b60405180910390f35b610292600480360381019061028d9190612725565b610918565b60405161029f9190612780565b60405180910390f35b6102c260048036038101906102bd919061279b565b61094c565b6040516102cf9190612780565b60405180910390f35b6102e0610980565b6040516102ed91906127e1565b60405180910390f35b6102fe6109a8565b60405161030b919061280b565b60405180910390f35b61031c6109d0565b005b6103386004803603810190610333919061288b565b6109d2565b6040516103459190612780565b60405180910390f35b610368600480360381019061036391906128d8565b610a38565b6040516103759190612780565b60405180910390f35b6103986004803603810190610393919061279b565b610a6c565b6040516103a5919061280b565b60405180910390f35b6103c860048036038101906103c3919061279b565b610a93565b005b6103e460048036038101906103df919061292b565b610ac5565b6040516103f19190612780565b60405180910390f35b610402610af9565b60405161040f91906126a8565b60405180910390f35b610420610b11565b60405161042d91906126a8565b60405180910390f35b61043e610b29565b60405161044b91906126a8565b60405180910390f35b61046e6004803603810190610469919061292b565b610b41565b005b610478610b73565b60405161048591906126a8565b60405180910390f35b610496610b8b565b6040516104a391906126a8565b60405180910390f35b6104b4610ba3565b6040516104c191906126a8565b60405180910390f35b6104d2610bbb565b6040516104df91906126a8565b60405180910390f35b61050260048036038101906104fd919061279b565b610bd3565b60405161050f919061280b565b60405180910390f35b610532600480360381019061052d91906129ae565b610bfa565b005b61053c610c2c565b604051610549919061280b565b60405180910390f35b61055a610c50565b604051610567919061280b565b60405180910390f35b610578610c78565b60405161058591906126a8565b60405180910390f35b610596610c90565b6040516105a391906126a8565b60405180910390f35b6105b4610ca8565b6040516105c191906126a8565b60405180910390f35b6105d2610cc0565b6040516105df91906126a8565b60405180910390f35b61060260048036038101906105fd91906129ae565b610cd8565b005b61060c610d0a565b6040516106199190612acc565b60405180910390f35b61063c6004803603810190610637919061292b565b610d19565b005b61065860048036038101906106539190612725565b610d4b565b6040516106659190612780565b60405180910390f35b610676610d7f565b60405161068391906126a8565b60405180910390f35b610694610d97565b6040516106a191906126a8565b60405180910390f35b6106b2610daf565b6040516106bf919061280b565b60405180910390f35b6106d0610dbb565b6040516106dd919061280b565b60405180910390f35b61070060048036038101906106fb9190612aee565b610ddf565b60405161070d919061280b565b60405180910390f35b61071e610e13565b60405161072b91906126a8565b60405180910390f35b61073c610e2b565b60405161074991906126a8565b60405180910390f35b61075a610e43565b60405161076791906126a8565b60405180910390f35b610778610e5b565b005b610782610e5d565b60405161078f91906126a8565b60405180910390f35b6107a0610e75565b6040516107ad9190612780565b60405180910390f35b6107d060048036038101906107cb919061292b565b610ea9565b6040516107dd91906126a8565b60405180910390f35b61080060048036038101906107fb919061279b565b610ed4565b60405161080e929190612bc7565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff81111561085357610852612bf7565b5b6040519080825280602002602001820160405280156108815781602001602082028036833780820191505090505b50905060005b7f00000000000000000000000000000000000000000000000000000000000000008110156108e457670de0b6b3a76400008282815181106108cb576108ca612c26565b5b6020026020010181815250508080600101915050610887565b5090565b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b83839050811015610a2c57610a118484838181106109f7576109f6612c26565b5b9050602002016020810190610a0c919061279b565b61182e565b610a1f576000915050610a32565b80806001019150506109d6565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a778261182e565b610a82576000610a8c565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b732f85824b2b38f179e451988670935d315b5b969281565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b73fed95453678920c1b7b3a81f033ca02a2722555681565b73777fba3666fa7747476a34577fccc404b263e09f81565b6000610bde8261182e565b610be9576000610bf3565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b73220230eda8f50067dd9e4729345dabcce0c6154281565b73a7241994267682de4de7ef62f52dc2c783d1784b81565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610d14611dae565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73281754ab58391a478b7aa4e7f39991cfb41118c481565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b736eed457c20603edae50c3a112caa1a9425321bd081565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b565b73b9c63a350a04d8bd245d18928a26ee036352ddd881565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610eb3611dae565b8281518110610ec557610ec4612c26565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f5f57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611829565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fe657826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611829565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361106d57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611829565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110d75782604051806060016040528060228152602001612c796022913991509150611829565b73220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361115e57826040518060400160405280601981526020017f68747470733a2f2f756d622e7374616b6572732e776f726c640000000000000081525091509150611829565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111e557826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611829565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361124f5782604051806060016040528060238152602001612c566023913991509150611829565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112d657826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611829565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113405782604051806060016040528060278152602001612cbf6027913991509150611829565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113c757826040518060400160405280601881526020017f68747470733a2f2f756d622e68617368717561726b2e696f000000000000000081525091509150611829565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114315782604051806060016040528060248152602001612c9b6024913991509150611829565b73b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361149b5782604051806060016040528060258152602001612ce66025913991509150611829565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152257826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611829565b73777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361158c5782604051806060016040528060278152602001612d2e6027913991509150611829565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361161357826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611829565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361169a57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611829565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036117045782604051806060016040528060238152602001612d0b6023913991509150611829565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361178b57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611829565b73fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361181257826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612d6e6f64652e636d7431332e6575000081525091509150611829565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806118bd575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061190757507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611951575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061199b575073220230eda8f50067dd9e4729345dabcce0c6154273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806119e557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a2f575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611a7957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ac3575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b0d5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611b57575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611ba1575073b9c63a350a04d8bd245d18928a26ee036352ddd873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611beb57507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c35575073777fba3666fa7747476a34577fccc404b263e09f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611c7f5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611cc9575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d135750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611d5d575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611da7575073fed95453678920c1b7b3a81f033ca02a2722555673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff811115611dec57611deb612bf7565b5b604051908082528060200260200182016040528015611e1a5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611e4657611e45612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611ea957611ea8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611f0c57611f0b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611f6f57611f6e612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073220230eda8f50067dd9e4729345dabcce0c6154281600481518110611fd257611fd1612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac8160058151811061203557612034612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a388160068151811061209857612097612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa4719653111816007815181106120fb576120fa612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b8160088151811061215e5761215d612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff27144816009815181106121c1576121c0612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600a8151811061222457612223612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073b9c63a350a04d8bd245d18928a26ee036352ddd881600b8151811061228757612286612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600c815181106122ea576122e9612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073777fba3666fa7747476a34577fccc404b263e09f81600d8151811061234d5761234c612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600e815181106123b0576123af612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600f8151811061241357612412612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd08160108151811061247657612475612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb816011815181106124d9576124d8612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073fed95453678920c1b7b3a81f033ca02a272255568160128151811061253c5761253b612c26565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6125bc816125a9565b82525050565b60006125ce83836125b3565b60208301905092915050565b6000602082019050919050565b60006125f28261257d565b6125fc8185612588565b935061260783612599565b8060005b8381101561263857815161261f88826125c2565b975061262a836125da565b92505060018101905061260b565b5085935050505092915050565b6000602082019050818103600083015261265f81846125e7565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061269282612667565b9050919050565b6126a281612687565b82525050565b60006020820190506126bd6000830184612699565b92915050565b600080fd5b600080fd5b6126d681612687565b81146126e157600080fd5b50565b6000813590506126f3816126cd565b92915050565b612702816125a9565b811461270d57600080fd5b50565b60008135905061271f816126f9565b92915050565b6000806040838503121561273c5761273b6126c3565b5b600061274a858286016126e4565b925050602061275b85828601612710565b9150509250929050565b60008115159050919050565b61277a81612765565b82525050565b60006020820190506127956000830184612771565b92915050565b6000602082840312156127b1576127b06126c3565b5b60006127bf848285016126e4565b91505092915050565b6000819050919050565b6127db816127c8565b82525050565b60006020820190506127f660008301846127d2565b92915050565b612805816125a9565b82525050565b600060208201905061282060008301846127fc565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261284b5761284a612826565b5b8235905067ffffffffffffffff8111156128685761286761282b565b5b60208301915083602082028301111561288457612883612830565b5b9250929050565b600080602083850312156128a2576128a16126c3565b5b600083013567ffffffffffffffff8111156128c0576128bf6126c8565b5b6128cc85828601612835565b92509250509250929050565b6000806000606084860312156128f1576128f06126c3565b5b60006128ff868287016126e4565b9350506020612910868287016126e4565b925050604061292186828701612710565b9150509250925092565b600060208284031215612941576129406126c3565b5b600061294f84828501612710565b91505092915050565b60008083601f84011261296e5761296d612826565b5b8235905067ffffffffffffffff81111561298b5761298a61282b565b5b6020830191508360018202830111156129a7576129a6612830565b5b9250929050565b6000806000604084860312156129c7576129c66126c3565b5b60006129d5868287016126e4565b935050602084013567ffffffffffffffff8111156129f6576129f56126c8565b5b612a0286828701612958565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b612a4381612687565b82525050565b6000612a558383612a3a565b60208301905092915050565b6000602082019050919050565b6000612a7982612a0e565b612a838185612a19565b9350612a8e83612a2a565b8060005b83811015612abf578151612aa68882612a49565b9750612ab183612a61565b925050600181019050612a92565b5085935050505092915050565b60006020820190508181036000830152612ae68184612a6e565b905092915050565b60008060408385031215612b0557612b046126c3565b5b6000612b13858286016126e4565b9250506020612b24858286016126e4565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612b68578082015181840152602081019050612b4d565b83811115612b77576000848401525b50505050565b6000601f19601f8301169050919050565b6000612b9982612b2e565b612ba38185612b39565b9350612bb3818560208601612b4a565b612bbc81612b7d565b840191505092915050565b6000604082019050612bdc6000830185612699565b8181036020830152612bee8184612b8e565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6170692e76616c696461747269756d2e636c756268747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6d68747470733a2f2f756d626e6f64652e626c6f636b636861696e6c69766572706f6f6c2e636f6da26469706673582212209a1752a9ea487818b8a4d658f151da9487c0cc92638142159bacde7ec2d21f7564736f6c634300080d0033", + "numDeployments": 2, + "solcInputHash": "dc68422c0ad35a4fe46d461b096b9383", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_validatorsCount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"NotSupported\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"minAmountForStake\",\"type\":\"uint256\"}],\"name\":\"LogMinAmountForStake\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"LogValidatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"NUMBER_OF_VALIDATORS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ONE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TOTAL_SUPPLY\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_0\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_1\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_10\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_11\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_12\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_13\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_14\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_2\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_3\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_4\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_5\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_6\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_7\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_8\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VALIDATOR_9\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_ix\",\"type\":\"uint256\"}],\"name\":\"addresses\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validator\",\"type\":\"address\"}],\"name\":\"balances\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"create\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"exit\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBalances\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"allBalances\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumberOfValidators\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"receiveApproval\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"register\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"remove\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"setMinAmountForStake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"stake\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"update\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_id\",\"type\":\"address\"}],\"name\":\"validators\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"location\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_validators\",\"type\":\"address[]\"}],\"name\":\"verifyValidators\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addresses(uint256)\":{\"details\":\"gets validator address for provided index\",\"params\":{\"_ix\":\"index in array of list of all validators wallets\"}},\"balanceOf(address)\":{\"details\":\"to follow ERC20 interface\"},\"exit()\":{\"details\":\"unstake and withdraw all tokens\"},\"getName()\":{\"details\":\"to follow Registrable interface\"},\"getNumberOfValidators()\":{\"returns\":{\"_0\":\"total number of registered validators (with and without balance)\"}},\"register()\":{\"details\":\"to follow Registrable interface\"},\"totalSupply()\":{\"details\":\"to follow ERC20 interface\"},\"unregister()\":{\"details\":\"to follow Registrable interface\"},\"validators(address)\":{\"params\":{\"_id\":\"address of validator\"},\"returns\":{\"id\":\"address of validator\",\"location\":\"URL of validator\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":\"StakingBankStaticProd\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":0},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBank.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IStakingBank is IERC20 {\\n /// @param id address of validator wallet\\n /// @param location URL of the validator API\\n struct Validator {\\n address id;\\n string location;\\n }\\n\\n event LogValidatorRegistered(address indexed id);\\n event LogValidatorUpdated(address indexed id);\\n event LogValidatorRemoved(address indexed id);\\n event LogMinAmountForStake(uint256 minAmountForStake);\\n\\n /// @dev setter for `minAmountForStake`\\n function setMinAmountForStake(uint256 _minAmountForStake) external;\\n\\n /// @dev allows to stake `token` by validators\\n /// Validator needs to approve StakingBank beforehand\\n /// @param _value amount of tokens to stake\\n function stake(uint256 _value) external;\\n\\n /// @dev notification about approval from `_from` address on UMB token\\n /// Staking bank will stake max approved amount from `_from` address\\n /// @param _from address which approved token spend for IStakingBank\\n function receiveApproval(address _from) external returns (bool success);\\n\\n /// @dev withdraws stake tokens\\n /// it throws, when balance will be less than required minimum for stake\\n /// to withdraw all use `exit`\\n function withdraw(uint256 _value) external returns (bool success);\\n\\n /// @dev unstake and withdraw all tokens\\n function exit() external returns (bool success);\\n\\n /// @dev creates (register) new validator\\n /// @param _id validator address\\n /// @param _location location URL of the validator API\\n function create(address _id, string calldata _location) external;\\n\\n /// @dev removes validator\\n /// @param _id validator wallet\\n function remove(address _id) external;\\n\\n /// @dev updates validator location\\n /// @param _id validator wallet\\n /// @param _location new validator URL\\n function update(address _id, string calldata _location) external;\\n\\n /// @return total number of registered validators (with and without balance)\\n function getNumberOfValidators() external view returns (uint256);\\n\\n /// @dev gets validator address for provided index\\n /// @param _ix index in array of list of all validators wallets\\n function addresses(uint256 _ix) external view returns (address);\\n\\n /// @param _id address of validator\\n /// @return id address of validator\\n /// @return location URL of validator\\n function validators(address _id) external view returns (address id, string memory location);\\n}\\n\",\"keccak256\":\"0x2c518aeab8b0b3a364fafaec559d3ff0dc6a119f8d203fa31ef7ad667ca0f7b9\",\"license\":\"MIT\"},\"contracts/interfaces/StakingBankStaticNotSupported.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./IStakingBank.sol\\\";\\n\\nabstract contract StakingBankStaticNotSupported is IStakingBank {\\n error NotSupported();\\n\\n function create(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function update(address, string calldata) external pure {\\n revert NotSupported();\\n }\\n\\n function remove(address) external pure {\\n revert NotSupported();\\n }\\n\\n function transfer(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function transferFrom(address, address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function receiveApproval(address) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function allowance(address, address) external pure returns (uint256) {\\n revert NotSupported();\\n }\\n\\n function approve(address, uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function stake(uint256) external pure {\\n revert NotSupported();\\n }\\n\\n function withdraw(uint256) external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function exit() external pure returns (bool) {\\n revert NotSupported();\\n }\\n\\n function setMinAmountForStake(uint256) external pure {\\n revert NotSupported();\\n }\\n}\\n\",\"keccak256\":\"0xa899ad9000220b04bc3f63f762a9a6a76dcc09449427e7774a53f4ceda9c1cf8\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStatic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"../interfaces/StakingBankStaticNotSupported.sol\\\";\\n\\n/// @dev Because we are using PoA in UMB oracle, staked balance does not matter. What's matter is, if signer is\\n/// validator or not. In this case we can optimise `StakingBank` and make it static for better gas performance.\\nabstract contract StakingBankStatic is StakingBankStaticNotSupported {\\n uint256 public constant ONE = 1e18;\\n\\n uint256 public immutable NUMBER_OF_VALIDATORS; // solhint-disable-line var-name-mixedcase\\n uint256 public immutable TOTAL_SUPPLY; // solhint-disable-line var-name-mixedcase\\n\\n constructor(uint256 _validatorsCount) {\\n NUMBER_OF_VALIDATORS = _validatorsCount;\\n TOTAL_SUPPLY = _validatorsCount * ONE;\\n\\n _assertValidSetup(_validatorsCount);\\n }\\n\\n function balances(address _validator) external view returns (uint256) {\\n return _isValidator(_validator) ? ONE : 0;\\n }\\n\\n function verifyValidators(address[] calldata _validators) external view returns (bool) {\\n for (uint256 i; i < _validators.length;) {\\n if (!_isValidator(_validators[i])) return false;\\n unchecked { i++; }\\n }\\n\\n return true;\\n }\\n\\n function getNumberOfValidators() external view returns (uint256) {\\n return NUMBER_OF_VALIDATORS;\\n }\\n\\n function getAddresses() external view returns (address[] memory) {\\n return _addresses();\\n }\\n\\n function getBalances() external view returns (uint256[] memory allBalances) {\\n allBalances = new uint256[](NUMBER_OF_VALIDATORS);\\n\\n for (uint256 i; i < NUMBER_OF_VALIDATORS;) {\\n allBalances[i] = ONE;\\n\\n unchecked {\\n // we will not have enough data to overflow\\n i++;\\n }\\n }\\n }\\n\\n function addresses(uint256 _ix) external view returns (address) {\\n return _addresses()[_ix];\\n }\\n\\n function validators(address _id) external view virtual returns (address id, string memory location);\\n\\n /// @dev to follow ERC20 interface\\n function balanceOf(address _account) external view returns (uint256) {\\n return _isValidator(_account) ? ONE : 0;\\n }\\n\\n /// @dev to follow ERC20 interface\\n function totalSupply() external view returns (uint256) {\\n return TOTAL_SUPPLY;\\n }\\n\\n /// @dev to follow Registrable interface\\n function getName() external pure returns (bytes32) {\\n return \\\"StakingBank\\\";\\n }\\n\\n /// @dev to follow Registrable interface\\n function register() external pure {\\n // there are no requirements atm\\n }\\n\\n /// @dev to follow Registrable interface\\n function unregister() external pure {\\n // there are no requirements atm\\n }\\n\\n function _addresses() internal view virtual returns (address[] memory);\\n\\n function _isValidator(address _validator) internal view virtual returns (bool);\\n\\n function _assertValidSetup(uint256 _validatorsCount) internal view virtual{\\n address[] memory list = _addresses();\\n require(list.length == _validatorsCount);\\n\\n for (uint256 i; i < _validatorsCount;) {\\n require(_isValidator(list[i]));\\n\\n unchecked { i ++; }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfcc53ff98b0f1c42e1bc7345a1535fdc4e938ef40d323600ead94b2ece59a381\",\"license\":\"MIT\"},\"contracts/stakingBankStatic/StakingBankStaticProd.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./StakingBankStatic.sol\\\";\\n\\ncontract StakingBankStaticProd is StakingBankStatic {\\n address public constant VALIDATOR_0 = 0x977Ba523420110e230643B772Fe9cF955e11dA7B;\\n address public constant VALIDATOR_1 = 0xe2422b23e52bc13ebA04d7FbB9F332Deb43360fB;\\n\\n // external order is based on validators submits on AVAX for Apr 2023\\n address public constant VALIDATOR_2 = 0x57F404aD75e371c1A539589C1eFCA12e0C6980AD;\\n address public constant VALIDATOR_3 = 0xD56C6A4f64E0bD70260472d1DB6Cf5825858CB0d;\\n address public constant VALIDATOR_4 = 0x93FdcAB283b0BcAc48157590af482E1CFd6af6aC;\\n address public constant VALIDATOR_5 = 0xCd733E06B06083d52fC5867E8E3432aA5c103A38;\\n address public constant VALIDATOR_6 = 0x42e210b110c6aa49CdfA7ceF1444Aa4719653111;\\n address public constant VALIDATOR_7 = 0x501731c6a69803a53Ec6c3e12f293c247cE1092B;\\n address public constant VALIDATOR_8 = 0x8bF9661F1b247522C75DD0FE84355aD2EfF27144;\\n address public constant VALIDATOR_9 = 0x281754Ab58391A478B7aA4E7f39991CfB41118c4;\\n address public constant VALIDATOR_10 = 0x57A51D5BDcE188c2295fCA3b4687475a54E65A02;\\n address public constant VALIDATOR_11 = 0x2F85824B2B38F179E451988670935d315b5b9692;\\n address public constant VALIDATOR_12 = 0xA7241994267682de4dE7Ef62f52dc2C783d1784B;\\n address public constant VALIDATOR_13 = 0x6eEd457C20603EDAE50C3A112CAA1a9425321bD0;\\n address public constant VALIDATOR_14 = 0xC5a7650c2725a7B6A39f15cb9FbffC7af357AFeb;\\n\\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\\n\\n // solhint-disable-next-line code-complexity\\n function validators(address _id) external pure override returns (address id, string memory location) {\\n if (_id == VALIDATOR_0) return (_id, \\\"https://validator.umb.network\\\");\\n if (_id == VALIDATOR_1) return (_id, \\\"https://validator2.umb.network\\\");\\n if (_id == VALIDATOR_2) return (_id, \\\"https://umbrella.artemahr.tech\\\");\\n if (_id == VALIDATOR_3) return (_id, \\\"https://umb.vtabsolutions.com:3030\\\");\\n if (_id == VALIDATOR_4) return (_id, \\\"https://umbrella.crazywhale.es\\\");\\n if (_id == VALIDATOR_5) return (_id, \\\"https://umbrella-node.gateomega.com\\\");\\n if (_id == VALIDATOR_6) return (_id, \\\"https://umb.anorak.technology\\\");\\n if (_id == VALIDATOR_7) return (_id, \\\"https://umbrella.validator.infstones.io\\\");\\n if (_id == VALIDATOR_8) return (_id, \\\"https://umb.hashkey.cloud\\\");\\n if (_id == VALIDATOR_9) return (_id, \\\"http://umbrella.staking4all.org:3000\\\");\\n if (_id == VALIDATOR_10) return (_id, \\\"http://5.161.78.230:3000\\\");\\n if (_id == VALIDATOR_11) return (_id, \\\"https://umb-api.staking.rocks\\\");\\n if (_id == VALIDATOR_12) return (_id, \\\"https://rpc.urbanhq.net\\\");\\n if (_id == VALIDATOR_13) return (_id, \\\"https://umbrella-node.ankastake.com\\\");\\n if (_id == VALIDATOR_14) return (_id, \\\"https://umbrella.tchambrella.com\\\");\\n\\n return (address(0), \\\"\\\");\\n }\\n\\n function _addresses() internal view override returns (address[] memory) {\\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\\n\\n list[0] = VALIDATOR_0;\\n list[1] = VALIDATOR_1;\\n list[2] = VALIDATOR_2;\\n list[3] = VALIDATOR_3;\\n list[4] = VALIDATOR_4;\\n list[5] = VALIDATOR_5;\\n list[6] = VALIDATOR_6;\\n list[7] = VALIDATOR_7;\\n list[8] = VALIDATOR_8;\\n list[9] = VALIDATOR_9;\\n list[10] = VALIDATOR_10;\\n list[11] = VALIDATOR_11;\\n list[12] = VALIDATOR_12;\\n list[13] = VALIDATOR_13;\\n list[14] = VALIDATOR_14;\\n\\n return list;\\n }\\n\\n function _isValidator(address _validator) internal pure override returns (bool) {\\n return (\\n _validator == VALIDATOR_0\\n || _validator == VALIDATOR_1\\n || _validator == VALIDATOR_2\\n || _validator == VALIDATOR_3\\n || _validator == VALIDATOR_4\\n || _validator == VALIDATOR_5\\n || _validator == VALIDATOR_6\\n || _validator == VALIDATOR_7\\n || _validator == VALIDATOR_8\\n || _validator == VALIDATOR_9\\n || _validator == VALIDATOR_10\\n || _validator == VALIDATOR_11\\n || _validator == VALIDATOR_12\\n || _validator == VALIDATOR_13\\n || _validator == VALIDATOR_14\\n );\\n }\\n}\\n\",\"keccak256\":\"0xcf8016c7d7325800fb6ac9f7afd34804b738daded6239139b23f894855a4f98b\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c06040523480156200001157600080fd5b50604051620034f8380380620034f8833981810160405281019062000037919062000beb565b808060808181525050670de0b6b3a76400008162000056919062000c4c565b60a081815250506200006e816200007660201b60201c565b505062000d0b565b600062000088620000ef60201b60201c565b9050818151146200009857600080fd5b60005b82811015620000ea57620000d2828281518110620000be57620000bd62000cad565b5b60200260200101516200074560201b60201c565b620000dc57600080fd5b80806001019150506200009b565b505050565b6060600060805167ffffffffffffffff81111562000112576200011162000cdc565b5b604051908082528060200260200182016040528015620001415781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b8160008151811062000170576200016f62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110620001d657620001d562000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad816002815181106200023c576200023b62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110620002a257620002a162000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac8160048151811062000308576200030762000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a38816005815181106200036e576200036d62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa471965311181600681518110620003d457620003d362000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b816007815181106200043a576200043962000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff2714481600881518110620004a0576200049f62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c48160098151811062000506576200050562000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600a815181106200056c576200056b62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600b81518110620005d257620005d162000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600c8151811062000638576200063762000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081600d815181106200069e576200069d62000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81600e8151811062000704576200070362000cad565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480620007d5575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806200082057507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806200086b575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80620008b657507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000901575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806200094c57507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000997575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80620009e25750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a2d575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000a7857507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ac35750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b0e575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000b595750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8062000ba4575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b600080fd5b6000819050919050565b62000bc58162000bb0565b811462000bd157600080fd5b50565b60008151905062000be58162000bba565b92915050565b60006020828403121562000c045762000c0362000bab565b5b600062000c148482850162000bd4565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600062000c598262000bb0565b915062000c668362000bb0565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161562000ca25762000ca162000c1d565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60805160a0516127a462000d54600039600081816109080152610b72015260008181610777015281816107e501528181610b9801528181610ce901526119a601526127a46000f3fe608060405234801561001057600080fd5b50600436106101ed5760003560e01c8062113e08146101f2578063015f7ed61461021057806303a1e2241461022e578063095ea7b31461024c5780630db18e371461027c57806317d7de7c146102ac57806318160ddd146102ca5780631aa3a008146102e85780631d4f9ce0146102f257806323b872dd1461032257806327e235e31461035257806329092d0e146103825780632e1a7d4d1461039e578063398b056e146103ce578063411ff497146103ec57806345f9f8251461040a57806352b41e351461042857806354755335146104445780635dc4bfd31461046257806369dc7ae41461048057806370a082311461049e578063838e7c3a146104ce578063902d55a5146104ea5780639031d9131461050857806390ff7e2e14610526578063989b6996146105445780639f0e948414610562578063a15ab08d14610580578063a39fac121461059c578063a694fc3a146105ba578063a9059cbb146105d6578063b2119eac14610606578063b49b084214610624578063c2ee3a0814610642578063db73177714610660578063dd62ed3e1461067e578063e2dc7a1a146106ae578063e79a198f146106cc578063e985e008146106d6578063e9fad8ee146106f4578063edf26d9b14610712578063fa52c7d814610742575b600080fd5b6101fa610773565b60405161020791906120ab565b60405180910390f35b610218610844565b604051610225919061210e565b60405180910390f35b61023661085c565b604051610243919061210e565b60405180910390f35b6102666004803603810190610261919061218b565b610874565b60405161027391906121e6565b60405180910390f35b61029660048036038101906102919190612201565b6108a8565b6040516102a391906121e6565b60405180910390f35b6102b46108dc565b6040516102c19190612247565b60405180910390f35b6102d2610904565b6040516102df9190612271565b60405180910390f35b6102f061092c565b005b61030c600480360381019061030791906122f1565b61092e565b60405161031991906121e6565b60405180910390f35b61033c6004803603810190610337919061233e565b610994565b60405161034991906121e6565b60405180910390f35b61036c60048036038101906103679190612201565b6109c8565b6040516103799190612271565b60405180910390f35b61039c60048036038101906103979190612201565b6109ef565b005b6103b860048036038101906103b39190612391565b610a21565b6040516103c591906121e6565b60405180910390f35b6103d6610a55565b6040516103e3919061210e565b60405180910390f35b6103f4610a6d565b604051610401919061210e565b60405180910390f35b610412610a85565b60405161041f919061210e565b60405180910390f35b610442600480360381019061043d9190612391565b610a9d565b005b61044c610acf565b604051610459919061210e565b60405180910390f35b61046a610ae7565b604051610477919061210e565b60405180910390f35b610488610aff565b604051610495919061210e565b60405180910390f35b6104b860048036038101906104b39190612201565b610b17565b6040516104c59190612271565b60405180910390f35b6104e860048036038101906104e39190612414565b610b3e565b005b6104f2610b70565b6040516104ff9190612271565b60405180910390f35b610510610b94565b60405161051d9190612271565b60405180910390f35b61052e610bbc565b60405161053b919061210e565b60405180910390f35b61054c610bd4565b604051610559919061210e565b60405180910390f35b61056a610bec565b604051610577919061210e565b60405180910390f35b61059a60048036038101906105959190612414565b610c04565b005b6105a4610c36565b6040516105b19190612532565b60405180910390f35b6105d460048036038101906105cf9190612391565b610c45565b005b6105f060048036038101906105eb919061218b565b610c77565b6040516105fd91906121e6565b60405180910390f35b61060e610cab565b60405161061b919061210e565b60405180910390f35b61062c610cc3565b604051610639919061210e565b60405180910390f35b61064a610cdb565b6040516106579190612271565b60405180910390f35b610668610ce7565b6040516106759190612271565b60405180910390f35b61069860048036038101906106939190612554565b610d0b565b6040516106a59190612271565b60405180910390f35b6106b6610d3f565b6040516106c3919061210e565b60405180910390f35b6106d4610d57565b005b6106de610d59565b6040516106eb919061210e565b60405180910390f35b6106fc610d71565b60405161070991906121e6565b60405180910390f35b61072c60048036038101906107279190612391565b610da5565b604051610739919061210e565b60405180910390f35b61075c60048036038101906107579190612201565b610dd0565b60405161076a92919061262d565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156107af576107ae61265d565b5b6040519080825280602002602001820160405280156107dd5781602001602082028036833780820191505090505b50905060005b7f000000000000000000000000000000000000000000000000000000000000000081101561084057670de0b6b3a76400008282815181106108275761082661268c565b5b60200260200101818152505080806001019150506107e3565b5090565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b838390508110156109885761096d8484838181106109535761095261268c565b5b90506020020160208101906109689190612201565b611548565b61097b57600091505061098e565b8080600101915050610932565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006109d382611548565b6109de5760006109e8565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73a7241994267682de4de7ef62f52dc2c783d1784b81565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b736eed457c20603edae50c3a112caa1a9425321bd081565b6000610b2282611548565b610b2d576000610b37565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73281754ab58391a478b7aa4e7f39991cfb41118c481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610c406119a0565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b565b732f85824b2b38f179e451988670935d315b5b969281565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610daf6119a0565b8281518110610dc157610dc061268c565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e5b57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611543565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610ee257826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611543565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f6957826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611543565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fd357826040518060600160405280602281526020016126df6022913991509150611543565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361105a57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611543565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110c457826040518060600160405280602381526020016126bc6023913991509150611543565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361114b57826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611543565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111b557826040518060600160405280602781526020016127256027913991509150611543565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361123c57826040518060400160405280601981526020017f68747470733a2f2f756d622e686173686b65792e636c6f75640000000000000081525091509150611543565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112a657826040518060600160405280602481526020016127016024913991509150611543565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361132d57826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611543565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113b457826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611543565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361143b57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611543565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114a5578260405180606001604052806023815260200161274c6023913991509150611543565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152c57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611543565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806115d7575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061162157507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061166b575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116b557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116ff575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061174957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611793575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806117dd5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611827575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061187157507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806118bb5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611905575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061194f5750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611999575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156119de576119dd61265d565b5b604051908082528060200260200182016040528015611a0c5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611a3857611a3761268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611a9b57611a9a61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611afe57611afd61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611b6157611b6061268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac81600481518110611bc457611bc361268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a3881600581518110611c2757611c2661268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa471965311181600681518110611c8a57611c8961268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b81600781518110611ced57611cec61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff2714481600881518110611d5057611d4f61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600981518110611db357611db261268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600a81518110611e1657611e1561268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600b81518110611e7957611e7861268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600c81518110611edc57611edb61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081600d81518110611f3f57611f3e61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81600e81518110611fa257611fa161268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6120228161200f565b82525050565b60006120348383612019565b60208301905092915050565b6000602082019050919050565b600061205882611fe3565b6120628185611fee565b935061206d83611fff565b8060005b8381101561209e5781516120858882612028565b975061209083612040565b925050600181019050612071565b5085935050505092915050565b600060208201905081810360008301526120c5818461204d565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006120f8826120cd565b9050919050565b612108816120ed565b82525050565b600060208201905061212360008301846120ff565b92915050565b600080fd5b600080fd5b61213c816120ed565b811461214757600080fd5b50565b60008135905061215981612133565b92915050565b6121688161200f565b811461217357600080fd5b50565b6000813590506121858161215f565b92915050565b600080604083850312156121a2576121a1612129565b5b60006121b08582860161214a565b92505060206121c185828601612176565b9150509250929050565b60008115159050919050565b6121e0816121cb565b82525050565b60006020820190506121fb60008301846121d7565b92915050565b60006020828403121561221757612216612129565b5b60006122258482850161214a565b91505092915050565b6000819050919050565b6122418161222e565b82525050565b600060208201905061225c6000830184612238565b92915050565b61226b8161200f565b82525050565b60006020820190506122866000830184612262565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126122b1576122b061228c565b5b8235905067ffffffffffffffff8111156122ce576122cd612291565b5b6020830191508360208202830111156122ea576122e9612296565b5b9250929050565b6000806020838503121561230857612307612129565b5b600083013567ffffffffffffffff8111156123265761232561212e565b5b6123328582860161229b565b92509250509250929050565b60008060006060848603121561235757612356612129565b5b60006123658682870161214a565b93505060206123768682870161214a565b925050604061238786828701612176565b9150509250925092565b6000602082840312156123a7576123a6612129565b5b60006123b584828501612176565b91505092915050565b60008083601f8401126123d4576123d361228c565b5b8235905067ffffffffffffffff8111156123f1576123f0612291565b5b60208301915083600182028301111561240d5761240c612296565b5b9250929050565b60008060006040848603121561242d5761242c612129565b5b600061243b8682870161214a565b935050602084013567ffffffffffffffff81111561245c5761245b61212e565b5b612468868287016123be565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6124a9816120ed565b82525050565b60006124bb83836124a0565b60208301905092915050565b6000602082019050919050565b60006124df82612474565b6124e9818561247f565b93506124f483612490565b8060005b8381101561252557815161250c88826124af565b9750612517836124c7565b9250506001810190506124f8565b5085935050505092915050565b6000602082019050818103600083015261254c81846124d4565b905092915050565b6000806040838503121561256b5761256a612129565b5b60006125798582860161214a565b925050602061258a8582860161214a565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156125ce5780820151818401526020810190506125b3565b838111156125dd576000848401525b50505050565b6000601f19601f8301169050919050565b60006125ff82612594565b612609818561259f565b93506126198185602086016125b0565b612622816125e3565b840191505092915050565b600060408201905061264260008301856120ff565b818103602083015261265481846125f4565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6da2646970667358221220b875faa4ff94a6ed380db1c82cfc4fcfdce28d00988b3f85c113e0332affbaa264736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101ed5760003560e01c8062113e08146101f2578063015f7ed61461021057806303a1e2241461022e578063095ea7b31461024c5780630db18e371461027c57806317d7de7c146102ac57806318160ddd146102ca5780631aa3a008146102e85780631d4f9ce0146102f257806323b872dd1461032257806327e235e31461035257806329092d0e146103825780632e1a7d4d1461039e578063398b056e146103ce578063411ff497146103ec57806345f9f8251461040a57806352b41e351461042857806354755335146104445780635dc4bfd31461046257806369dc7ae41461048057806370a082311461049e578063838e7c3a146104ce578063902d55a5146104ea5780639031d9131461050857806390ff7e2e14610526578063989b6996146105445780639f0e948414610562578063a15ab08d14610580578063a39fac121461059c578063a694fc3a146105ba578063a9059cbb146105d6578063b2119eac14610606578063b49b084214610624578063c2ee3a0814610642578063db73177714610660578063dd62ed3e1461067e578063e2dc7a1a146106ae578063e79a198f146106cc578063e985e008146106d6578063e9fad8ee146106f4578063edf26d9b14610712578063fa52c7d814610742575b600080fd5b6101fa610773565b60405161020791906120ab565b60405180910390f35b610218610844565b604051610225919061210e565b60405180910390f35b61023661085c565b604051610243919061210e565b60405180910390f35b6102666004803603810190610261919061218b565b610874565b60405161027391906121e6565b60405180910390f35b61029660048036038101906102919190612201565b6108a8565b6040516102a391906121e6565b60405180910390f35b6102b46108dc565b6040516102c19190612247565b60405180910390f35b6102d2610904565b6040516102df9190612271565b60405180910390f35b6102f061092c565b005b61030c600480360381019061030791906122f1565b61092e565b60405161031991906121e6565b60405180910390f35b61033c6004803603810190610337919061233e565b610994565b60405161034991906121e6565b60405180910390f35b61036c60048036038101906103679190612201565b6109c8565b6040516103799190612271565b60405180910390f35b61039c60048036038101906103979190612201565b6109ef565b005b6103b860048036038101906103b39190612391565b610a21565b6040516103c591906121e6565b60405180910390f35b6103d6610a55565b6040516103e3919061210e565b60405180910390f35b6103f4610a6d565b604051610401919061210e565b60405180910390f35b610412610a85565b60405161041f919061210e565b60405180910390f35b610442600480360381019061043d9190612391565b610a9d565b005b61044c610acf565b604051610459919061210e565b60405180910390f35b61046a610ae7565b604051610477919061210e565b60405180910390f35b610488610aff565b604051610495919061210e565b60405180910390f35b6104b860048036038101906104b39190612201565b610b17565b6040516104c59190612271565b60405180910390f35b6104e860048036038101906104e39190612414565b610b3e565b005b6104f2610b70565b6040516104ff9190612271565b60405180910390f35b610510610b94565b60405161051d9190612271565b60405180910390f35b61052e610bbc565b60405161053b919061210e565b60405180910390f35b61054c610bd4565b604051610559919061210e565b60405180910390f35b61056a610bec565b604051610577919061210e565b60405180910390f35b61059a60048036038101906105959190612414565b610c04565b005b6105a4610c36565b6040516105b19190612532565b60405180910390f35b6105d460048036038101906105cf9190612391565b610c45565b005b6105f060048036038101906105eb919061218b565b610c77565b6040516105fd91906121e6565b60405180910390f35b61060e610cab565b60405161061b919061210e565b60405180910390f35b61062c610cc3565b604051610639919061210e565b60405180910390f35b61064a610cdb565b6040516106579190612271565b60405180910390f35b610668610ce7565b6040516106759190612271565b60405180910390f35b61069860048036038101906106939190612554565b610d0b565b6040516106a59190612271565b60405180910390f35b6106b6610d3f565b6040516106c3919061210e565b60405180910390f35b6106d4610d57565b005b6106de610d59565b6040516106eb919061210e565b60405180910390f35b6106fc610d71565b60405161070991906121e6565b60405180910390f35b61072c60048036038101906107279190612391565b610da5565b604051610739919061210e565b60405180910390f35b61075c60048036038101906107579190612201565b610dd0565b60405161076a92919061262d565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156107af576107ae61265d565b5b6040519080825280602002602001820160405280156107dd5781602001602082028036833780820191505090505b50905060005b7f000000000000000000000000000000000000000000000000000000000000000081101561084057670de0b6b3a76400008282815181106108275761082661268c565b5b60200260200101818152505080806001019150506107e3565b5090565b7342e210b110c6aa49cdfa7cef1444aa471965311181565b738bf9661f1b247522c75dd0fe84355ad2eff2714481565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b838390508110156109885761096d8484838181106109535761095261268c565b5b90506020020160208101906109689190612201565b611548565b61097b57600091505061098e565b8080600101915050610932565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006109d382611548565b6109de5760006109e8565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73a7241994267682de4de7ef62f52dc2c783d1784b81565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb81565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73cd733e06b06083d52fc5867e8e3432aa5c103a3881565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d81565b736eed457c20603edae50c3a112caa1a9425321bd081565b6000610b2282611548565b610b2d576000610b37565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b7393fdcab283b0bcac48157590af482e1cfd6af6ac81565b73281754ab58391a478b7aa4e7f39991cfb41118c481565b73977ba523420110e230643b772fe9cf955e11da7b81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610c406119a0565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7357a51d5bdce188c2295fca3b4687475a54e65a0281565b7357f404ad75e371c1a539589c1efca12e0c6980ad81565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73501731c6a69803a53ec6c3e12f293c247ce1092b81565b565b732f85824b2b38f179e451988670935d315b5b969281565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610daf6119a0565b8281518110610dc157610dc061268c565b5b60200260200101519050919050565b6000606073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e5b57826040518060400160405280601d81526020017f68747470733a2f2f76616c696461746f722e756d622e6e6574776f726b00000081525091509150611543565b73e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610ee257826040518060400160405280601e81526020017f68747470733a2f2f76616c696461746f72322e756d622e6e6574776f726b000081525091509150611543565b7357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f6957826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e617274656d6168722e74656368000081525091509150611543565b73d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fd357826040518060600160405280602281526020016126df6022913991509150611543565b7393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361105a57826040518060400160405280601e81526020017f68747470733a2f2f756d6272656c6c612e6372617a797768616c652e6573000081525091509150611543565b73cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110c457826040518060600160405280602381526020016126bc6023913991509150611543565b7342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361114b57826040518060400160405280601d81526020017f68747470733a2f2f756d622e616e6f72616b2e746563686e6f6c6f677900000081525091509150611543565b73501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036111b557826040518060600160405280602781526020016127256027913991509150611543565b738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361123c57826040518060400160405280601981526020017f68747470733a2f2f756d622e686173686b65792e636c6f75640000000000000081525091509150611543565b73281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112a657826040518060600160405280602481526020016127016024913991509150611543565b7357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361132d57826040518060400160405280601881526020017f687474703a2f2f352e3136312e37382e3233303a33303030000000000000000081525091509150611543565b732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113b457826040518060400160405280601d81526020017f68747470733a2f2f756d622d6170692e7374616b696e672e726f636b7300000081525091509150611543565b73a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361143b57826040518060400160405280601781526020017f68747470733a2f2f7270632e757262616e68712e6e657400000000000000000081525091509150611543565b736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036114a5578260405180606001604052806023815260200161274c6023913991509150611543565b73c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361152c57826040518060400160405280602081526020017f68747470733a2f2f756d6272656c6c612e746368616d6272656c6c612e636f6d81525091509150611543565b600060405180602001604052806000815250915091505b915091565b600073977ba523420110e230643b772fe9cf955e11da7b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806115d7575073e2422b23e52bc13eba04d7fbb9f332deb43360fb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061162157507357f404ad75e371c1a539589c1efca12e0c6980ad73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061166b575073d56c6a4f64e0bd70260472d1db6cf5825858cb0d73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116b557507393fdcab283b0bcac48157590af482e1cfd6af6ac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806116ff575073cd733e06b06083d52fc5867e8e3432aa5c103a3873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061174957507342e210b110c6aa49cdfa7cef1444aa471965311173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611793575073501731c6a69803a53ec6c3e12f293c247ce1092b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806117dd5750738bf9661f1b247522c75dd0fe84355ad2eff2714473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611827575073281754ab58391a478b7aa4e7f39991cfb41118c473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061187157507357a51d5bdce188c2295fca3b4687475a54e65a0273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806118bb5750732f85824b2b38f179e451988670935d315b5b969273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611905575073a7241994267682de4de7ef62f52dc2c783d1784b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b8061194f5750736eed457c20603edae50c3a112caa1a9425321bd073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611999575073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156119de576119dd61265d565b5b604051908082528060200260200182016040528015611a0c5781602001602082028036833780820191505090505b50905073977ba523420110e230643b772fe9cf955e11da7b81600081518110611a3857611a3761268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073e2422b23e52bc13eba04d7fbb9f332deb43360fb81600181518110611a9b57611a9a61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357f404ad75e371c1a539589c1efca12e0c6980ad81600281518110611afe57611afd61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073d56c6a4f64e0bd70260472d1db6cf5825858cb0d81600381518110611b6157611b6061268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507393fdcab283b0bcac48157590af482e1cfd6af6ac81600481518110611bc457611bc361268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073cd733e06b06083d52fc5867e8e3432aa5c103a3881600581518110611c2757611c2661268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507342e210b110c6aa49cdfa7cef1444aa471965311181600681518110611c8a57611c8961268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073501731c6a69803a53ec6c3e12f293c247ce1092b81600781518110611ced57611cec61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050738bf9661f1b247522c75dd0fe84355ad2eff2714481600881518110611d5057611d4f61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073281754ab58391a478b7aa4e7f39991cfb41118c481600981518110611db357611db261268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507357a51d5bdce188c2295fca3b4687475a54e65a0281600a81518110611e1657611e1561268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050732f85824b2b38f179e451988670935d315b5b969281600b81518110611e7957611e7861268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073a7241994267682de4de7ef62f52dc2c783d1784b81600c81518110611edc57611edb61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050736eed457c20603edae50c3a112caa1a9425321bd081600d81518110611f3f57611f3e61268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c5a7650c2725a7b6a39f15cb9fbffc7af357afeb81600e81518110611fa257611fa161268c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b6120228161200f565b82525050565b60006120348383612019565b60208301905092915050565b6000602082019050919050565b600061205882611fe3565b6120628185611fee565b935061206d83611fff565b8060005b8381101561209e5781516120858882612028565b975061209083612040565b925050600181019050612071565b5085935050505092915050565b600060208201905081810360008301526120c5818461204d565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006120f8826120cd565b9050919050565b612108816120ed565b82525050565b600060208201905061212360008301846120ff565b92915050565b600080fd5b600080fd5b61213c816120ed565b811461214757600080fd5b50565b60008135905061215981612133565b92915050565b6121688161200f565b811461217357600080fd5b50565b6000813590506121858161215f565b92915050565b600080604083850312156121a2576121a1612129565b5b60006121b08582860161214a565b92505060206121c185828601612176565b9150509250929050565b60008115159050919050565b6121e0816121cb565b82525050565b60006020820190506121fb60008301846121d7565b92915050565b60006020828403121561221757612216612129565b5b60006122258482850161214a565b91505092915050565b6000819050919050565b6122418161222e565b82525050565b600060208201905061225c6000830184612238565b92915050565b61226b8161200f565b82525050565b60006020820190506122866000830184612262565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126122b1576122b061228c565b5b8235905067ffffffffffffffff8111156122ce576122cd612291565b5b6020830191508360208202830111156122ea576122e9612296565b5b9250929050565b6000806020838503121561230857612307612129565b5b600083013567ffffffffffffffff8111156123265761232561212e565b5b6123328582860161229b565b92509250509250929050565b60008060006060848603121561235757612356612129565b5b60006123658682870161214a565b93505060206123768682870161214a565b925050604061238786828701612176565b9150509250925092565b6000602082840312156123a7576123a6612129565b5b60006123b584828501612176565b91505092915050565b60008083601f8401126123d4576123d361228c565b5b8235905067ffffffffffffffff8111156123f1576123f0612291565b5b60208301915083600182028301111561240d5761240c612296565b5b9250929050565b60008060006040848603121561242d5761242c612129565b5b600061243b8682870161214a565b935050602084013567ffffffffffffffff81111561245c5761245b61212e565b5b612468868287016123be565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6124a9816120ed565b82525050565b60006124bb83836124a0565b60208301905092915050565b6000602082019050919050565b60006124df82612474565b6124e9818561247f565b93506124f483612490565b8060005b8381101561252557815161250c88826124af565b9750612517836124c7565b9250506001810190506124f8565b5085935050505092915050565b6000602082019050818103600083015261254c81846124d4565b905092915050565b6000806040838503121561256b5761256a612129565b5b60006125798582860161214a565b925050602061258a8582860161214a565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156125ce5780820151818401526020810190506125b3565b838111156125dd576000848401525b50505050565b6000601f19601f8301169050919050565b60006125ff82612594565b612609818561259f565b93506126198185602086016125b0565b612622816125e3565b840191505092915050565b600060408201905061264260008301856120ff565b818103602083015261265481846125f4565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f756d6272656c6c612d6e6f64652e676174656f6d6567612e636f6d68747470733a2f2f756d622e76746162736f6c7574696f6e732e636f6d3a33303330687474703a2f2f756d6272656c6c612e7374616b696e6734616c6c2e6f72673a3330303068747470733a2f2f756d6272656c6c612e76616c696461746f722e696e6673746f6e65732e696f68747470733a2f2f756d6272656c6c612d6e6f64652e616e6b617374616b652e636f6da2646970667358221220b875faa4ff94a6ed380db1c82cfc4fcfdce28d00988b3f85c113e0332affbaa264736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/rootstock_production/UmbrellaFeeds.json b/deployments/rootstock_production/UmbrellaFeeds.json index 96ea7952..89e6d47e 100644 --- a/deployments/rootstock_production/UmbrellaFeeds.json +++ b/deployments/rootstock_production/UmbrellaFeeds.json @@ -1,5 +1,5 @@ { - "address": "0xDa9A63D77406faa09d265413F4E128B54b5057e0", + "address": "0xDc823570a5673E4D386242249EAfA086c436AB9c", "abi": [ { "inputs": [ @@ -662,19 +662,19 @@ "type": "function" } ], - "transactionHash": "0x3474105ca85c0674ce95630c36de70afc26bdc03faea69f7fb3c2c882f3632f7", + "transactionHash": "0x0b350df0dc2af0b9d7a5efaf2342fbed37493f4466e722978ed74527caa7319b", "receipt": { "to": null, "from": "0xA6e4fFa19B213AbeA258ae72e8e1a209B9E543e7", - "contractAddress": "0xDa9A63D77406faa09d265413F4E128B54b5057e0", - "transactionIndex": 0, + "contractAddress": "0xDc823570a5673E4D386242249EAfA086c436AB9c", + "transactionIndex": 2, "gasUsed": "2529963", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xa58602b9297df6bbd7023c591ed39b1769671f8dfdbfebd33349e0c0501b15cf", - "transactionHash": "0x3474105ca85c0674ce95630c36de70afc26bdc03faea69f7fb3c2c882f3632f7", + "blockHash": "0xa823a3d04ad82956d95e37dc0499b1c3b2b709c8d21f77494595bd1ed3c0e382", + "transactionHash": "0x0b350df0dc2af0b9d7a5efaf2342fbed37493f4466e722978ed74527caa7319b", "logs": [], - "blockNumber": 6227927, - "cumulativeGasUsed": "2529963", + "blockNumber": 6872363, + "cumulativeGasUsed": "2642427", "status": 1, "byzantium": true }, @@ -684,7 +684,7 @@ 8 ], "numDeployments": 1, - "solcInputHash": "4db3e1d3dd51dbe508dc0a6a04352df6", + "solcInputHash": "dc68422c0ad35a4fe46d461b096b9383", "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"_contractRegistry\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"_requiredSignatures\",\"type\":\"uint16\"},{\"internalType\":\"uint8\",\"name\":\"_decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ArraysDataDoNotMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractInUse\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractNotInitialised\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ECDSAInvalidSignatureS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ECDSAInvalidSignatureV\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FeedNotExist\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRequiredSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotEnoughSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OldData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfOrder\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DECIMALS\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DEPLOYED_AT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ETH_PREFIX\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NAME\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REGISTRY\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REQUIRED_SIGNATURES\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"STAKING_BANK\",\"outputs\":[{\"internalType\":\"contract IStakingBankStatic\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"destroy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_keys\",\"type\":\"bytes32[]\"}],\"name\":\"getManyPriceData\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData[]\",\"name\":\"data\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_keys\",\"type\":\"bytes32[]\"}],\"name\":\"getManyPriceDataRaw\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData[]\",\"name\":\"data\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getPrice\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getPriceData\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData\",\"name\":\"data\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"getPriceDataByName\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData\",\"name\":\"data\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getPriceTimestamp\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"getPriceTimestampHeartbeat\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_priceKeys\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData[]\",\"name\":\"_priceDatas\",\"type\":\"tuple[]\"}],\"name\":\"hashData\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"}],\"name\":\"prices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData\",\"name\":\"data\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_hash\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"_v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"_r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_s\",\"type\":\"bytes32\"}],\"name\":\"recoverSigner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_priceKeys\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"data\",\"type\":\"uint8\"},{\"internalType\":\"uint24\",\"name\":\"heartbeat\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"price\",\"type\":\"uint128\"}],\"internalType\":\"struct IUmbrellaFeeds.PriceData[]\",\"name\":\"_priceDatas\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"struct IUmbrellaFeeds.Signature[]\",\"name\":\"_signatures\",\"type\":\"tuple[]\"}],\"name\":\"update\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_hash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"struct IUmbrellaFeeds.Signature[]\",\"name\":\"_signatures\",\"type\":\"tuple[]\"}],\"name\":\"verifySignatures\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Main contract for all on-chain data. Check `UmbrellaFeedsReader` to see how to integrate.\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_contractRegistry\":\"Registry address\",\"_decimals\":\"decimals for prices stored in this contract\",\"_requiredSignatures\":\"number of required signatures for accepting consensus submission\"}},\"destroy(string)\":{\"details\":\"destroys old contract there is sanity check that prevents abuse of destroy method\",\"params\":{\"_name\":\"string feed key to verify, that contract was initialised\"}},\"getManyPriceData(bytes32[])\":{\"details\":\"it will return array of price datas for provided `_keys` In case ony of feed does not exist, fallback call will be executed for that feed.\",\"params\":{\"_keys\":\"array of feed keys\"},\"returns\":{\"data\":\"PriceData array\"}},\"getManyPriceDataRaw(bytes32[])\":{\"details\":\"same as getManyPriceData() but does not revert on empty data.\"},\"getName()\":{\"details\":\"to follow Registrable interface\"},\"getPrice(bytes32)\":{\"params\":{\"_key\":\"hash of feed name\"},\"returns\":{\"price\":\"price\"}},\"getPriceData(bytes32)\":{\"details\":\"this is main endpoint for reading feeds. In case timestamp is empty (that means there is no data), contract will revert. If you do not need whole data from `PriceData` struct, you can save some gas by using other view methods that returns just what you need.\",\"params\":{\"_key\":\"hash of feed name\"},\"returns\":{\"data\":\"full PriceData struct\"}},\"getPriceDataByName(string)\":{\"details\":\"This method should be used only for Layer2 as it is more gas consuming than others views.\",\"params\":{\"_name\":\"string feed name\"},\"returns\":{\"data\":\"PriceData\"}},\"getPriceTimestamp(bytes32)\":{\"params\":{\"_key\":\"hash of feed name\"},\"returns\":{\"price\":\"price\",\"timestamp\":\"timestamp\"}},\"getPriceTimestampHeartbeat(bytes32)\":{\"params\":{\"_key\":\"hash of feed name\"},\"returns\":{\"heartbeat\":\"heartbeat\",\"price\":\"price\",\"timestamp\":\"timestamp\"}},\"hashData(bytes32[],(uint8,uint24,uint32,uint128)[])\":{\"details\":\"helper method for QA purposes\",\"returns\":{\"_0\":\"hash of data that are signed by validators (keys and priced data)\"}},\"prices(bytes32)\":{\"params\":{\"_key\":\"hash of feed name\"},\"returns\":{\"data\":\"full PriceData struct\"}},\"recoverSigner(bytes32,uint8,bytes32,bytes32)\":{\"params\":{\"_hash\":\"hashed of data\",\"_r\":\"part of signature\",\"_s\":\"part of signature\",\"_v\":\"part of signature\"},\"returns\":{\"_0\":\"signer address\"}},\"update(bytes32[],(uint8,uint24,uint32,uint128)[],(uint8,bytes32,bytes32)[])\":{\"details\":\"method for submitting consensus data\",\"params\":{\"_priceDatas\":\"PriceData signed by validators\",\"_priceKeys\":\"array of keys for `_priceDatas`\",\"_signatures\":\"validators signatures\"}},\"verifySignatures(bytes32,(uint8,bytes32,bytes32)[])\":{\"params\":{\"_hash\":\"hash of signed data\",\"_signatures\":\"array of validators signatures\"}}},\"stateVariables\":{\"DECIMALS\":{\"details\":\"decimals for prices stored in this contract\"},\"DEPLOYED_AT\":{\"details\":\"deployment time, used for protect for unintentional destroy\"},\"REGISTRY\":{\"details\":\"Registry contract where list of all addresses is stored. Fallback feature uses this registry to resolve newest `UmbrellaFeeds` address\"},\"REQUIRED_SIGNATURES\":{\"details\":\"minimal number of signatures required for accepting price submission (PoA)\"},\"STAKING_BANK\":{\"details\":\"StakingBank contract where list of validators is stored\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getManyPriceData(bytes32[])\":{\"notice\":\"If data for any key not exists, function will revert. Use `getManyPriceDataRaw` method if you don't want revert.\"},\"getManyPriceDataRaw(bytes32[])\":{\"notice\":\"This method does no revert if some data does not exists. Check `data.timestamp` to see if price exist, if it is 0, then it does not exist.\"},\"getPrice(bytes32)\":{\"notice\":\"method will revert if data for `_key` not exists.\"},\"getPriceData(bytes32)\":{\"notice\":\"method will revert if data for `_key` not exists.\"},\"getPriceDataByName(string)\":{\"notice\":\"It does not revert on empty data.\"},\"getPriceTimestamp(bytes32)\":{\"notice\":\"method will revert if data for `_key` not exists.\"},\"getPriceTimestampHeartbeat(bytes32)\":{\"notice\":\"method will revert if data for `_key` not exists.\"},\"prices(bytes32)\":{\"notice\":\"reader for mapping\"}},\"notice\":\"This contract can be destroyed and replaced with new one (with new address). For best gas efficiency you should pick one of two ways of integration: 1. make `UmbrellaFeeds` immutable and use fallback in case of selfdestruct. After new deployment, it is recommended to update address to avoid fallback and reduce gas cost to minimum. In long run this is most efficient solution, better than any proxy. 2. always check newest `UmbrellaFeeds` via `Regostry` and fallback will not be needed.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/onChainFeeds/UmbrellaFeeds.sol\":\"UmbrellaFeeds\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":0},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/interfaces/IRegistry.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\n\\ninterface IRegistry {\\n event LogRegistered(address indexed destination, bytes32 name);\\n\\n /// @dev imports new contract addresses and override old addresses, if they exist under provided name\\n /// This method can be used for contracts that for some reason do not have `getName` method\\n /// @param _names array of contract names that we want to register\\n /// @param _destinations array of contract addresses\\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external;\\n\\n /// @dev imports new contracts and override old addresses, if they exist.\\n /// Names of contracts are fetched directly from each contract by calling `getName`\\n /// @param _destinations array of contract addresses\\n function importContracts(address[] calldata _destinations) external;\\n\\n /// @dev this method ensure, that old and new contract is aware of it state in registry\\n /// Note: BSC registry does not have this method. This method was introduced in later stage.\\n /// @param _newContract address of contract that will replace old one\\n function atomicUpdate(address _newContract) external;\\n\\n /// @dev similar to `getAddress` but throws when contract name not exists\\n /// @param name contract name\\n /// @return contract address registered under provided name or throws, if does not exists\\n function requireAndGetAddress(bytes32 name) external view returns (address);\\n\\n /// @param name contract name in a form of bytes32\\n /// @return contract address registered under provided name\\n function getAddress(bytes32 name) external view returns (address);\\n\\n /// @param _name contract name\\n /// @return contract address assigned to the name or address(0) if not exists\\n function getAddressByString(string memory _name) external view returns (address);\\n\\n /// @dev helper method that converts string to bytes32,\\n /// you can use to to generate contract name\\n function stringToBytes32(string memory _string) external pure returns (bytes32 result);\\n}\\n\",\"keccak256\":\"0xa0099ecf4182138fda7a0733407784461410c245de67c1e7ba7cd7c9595e054f\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBank.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IStakingBank is IERC20 {\\n /// @param id address of validator wallet\\n /// @param location URL of the validator API\\n struct Validator {\\n address id;\\n string location;\\n }\\n\\n event LogValidatorRegistered(address indexed id);\\n event LogValidatorUpdated(address indexed id);\\n event LogValidatorRemoved(address indexed id);\\n event LogMinAmountForStake(uint256 minAmountForStake);\\n\\n /// @dev setter for `minAmountForStake`\\n function setMinAmountForStake(uint256 _minAmountForStake) external;\\n\\n /// @dev allows to stake `token` by validators\\n /// Validator needs to approve StakingBank beforehand\\n /// @param _value amount of tokens to stake\\n function stake(uint256 _value) external;\\n\\n /// @dev notification about approval from `_from` address on UMB token\\n /// Staking bank will stake max approved amount from `_from` address\\n /// @param _from address which approved token spend for IStakingBank\\n function receiveApproval(address _from) external returns (bool success);\\n\\n /// @dev withdraws stake tokens\\n /// it throws, when balance will be less than required minimum for stake\\n /// to withdraw all use `exit`\\n function withdraw(uint256 _value) external returns (bool success);\\n\\n /// @dev unstake and withdraw all tokens\\n function exit() external returns (bool success);\\n\\n /// @dev creates (register) new validator\\n /// @param _id validator address\\n /// @param _location location URL of the validator API\\n function create(address _id, string calldata _location) external;\\n\\n /// @dev removes validator\\n /// @param _id validator wallet\\n function remove(address _id) external;\\n\\n /// @dev updates validator location\\n /// @param _id validator wallet\\n /// @param _location new validator URL\\n function update(address _id, string calldata _location) external;\\n\\n /// @return total number of registered validators (with and without balance)\\n function getNumberOfValidators() external view returns (uint256);\\n\\n /// @dev gets validator address for provided index\\n /// @param _ix index in array of list of all validators wallets\\n function addresses(uint256 _ix) external view returns (address);\\n\\n /// @param _id address of validator\\n /// @return id address of validator\\n /// @return location URL of validator\\n function validators(address _id) external view returns (address id, string memory location);\\n}\\n\",\"keccak256\":\"0x2c518aeab8b0b3a364fafaec559d3ff0dc6a119f8d203fa31ef7ad667ca0f7b9\",\"license\":\"MIT\"},\"contracts/interfaces/IStakingBankStatic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"./IStakingBank.sol\\\";\\n\\n\\ninterface IStakingBankStatic is IStakingBank {\\n /// @param _validators array of validators addresses to verify\\n /// @return TRUE when all validators are valid, FALSE otherwise\\n function verifyValidators(address[] calldata _validators) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xb7829f090205357ae8c7b86490504897060650c149309362b95eacbeef88d8ba\",\"license\":\"MIT\"},\"contracts/interfaces/IUmbrellaFeeds.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IUmbrellaFeeds {\\n struct PriceData {\\n /// @dev this is placeholder, that can be used for some additional data\\n /// atm of creating this smart contract, it is only used as marker for removed data (when == type(uint8).max)\\n uint8 data;\\n /// @dev heartbeat: how often price data will be refreshed in case price stay flat\\n uint24 heartbeat;\\n /// @dev timestamp: price time, at this time validators run consensus\\n uint32 timestamp;\\n /// @dev price\\n uint128 price;\\n }\\n\\n struct Signature {\\n uint8 v;\\n bytes32 r;\\n bytes32 s;\\n }\\n\\n /// @dev method for submitting consensus data\\n /// @param _priceKeys array of keys for `_priceDatas`\\n /// @param _priceDatas PriceData signed by validators\\n /// @param _signatures validators signatures\\n function update(\\n bytes32[] calldata _priceKeys,\\n PriceData[] calldata _priceDatas,\\n Signature[] calldata _signatures\\n ) external;\\n\\n /// @dev it will return array of price datas for provided `_keys`\\n /// In case ony of feed does not exist, fallback call will be executed for that feed.\\n /// @notice If data for any key not exists, function will revert. Use `getManyPriceDataRaw` method if you don't\\n /// want revert.\\n /// @param _keys array of feed keys\\n /// @return data PriceData array\\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data);\\n\\n /// @dev same as getManyPriceData() but does not revert on empty data.\\n /// @notice This method does no revert if some data does not exists.\\n /// Check `data.timestamp` to see if price exist, if it is 0, then it does not exist.\\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data);\\n\\n /// @dev this is main endpoint for reading feeds.\\n /// In case timestamp is empty (that means there is no data), contract will revert.\\n /// If you do not need whole data from `PriceData` struct, you can save some gas by using other view methods that\\n /// returns just what you need.\\n /// @notice method will revert if data for `_key` not exists.\\n /// @param _key hash of feed name\\n /// @return data full PriceData struct\\n function getPriceData(bytes32 _key) external view returns (PriceData memory data);\\n\\n /// @notice reader for mapping\\n /// @param _key hash of feed name\\n /// @return data full PriceData struct\\n function prices(bytes32 _key) external view returns (PriceData memory data);\\n\\n /// @notice method will revert if data for `_key` not exists.\\n /// @param _key hash of feed name\\n /// @return price\\n function getPrice(bytes32 _key) external view returns (uint128 price);\\n\\n /// @notice method will revert if data for `_key` not exists.\\n /// @param _key hash of feed name\\n /// @return price\\n /// @return timestamp\\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp);\\n\\n /// @notice method will revert if data for `_key` not exists.\\n /// @param _key hash of feed name\\n /// @return price\\n /// @return timestamp\\n /// @return heartbeat\\n function getPriceTimestampHeartbeat(bytes32 _key)\\n external\\n view\\n returns (uint128 price, uint32 timestamp, uint24 heartbeat);\\n\\n /// @dev This method should be used only for Layer2 as it is more gas consuming than others views.\\n /// @notice It does not revert on empty data.\\n /// @param _name string feed name\\n /// @return data PriceData\\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data);\\n\\n /// @dev decimals for prices stored in this contract\\n function DECIMALS() external view returns (uint8); // solhint-disable-line func-name-mixedcase\\n}\\n\",\"keccak256\":\"0x3b89742a9ab465f00aa9cf8635a5dfdc02d7ecf9bad8f564bee7c15d8aea46cb\",\"license\":\"MIT\"},\"contracts/onChainFeeds/UmbrellaFeeds.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"../interfaces/IUmbrellaFeeds.sol\\\";\\nimport \\\"../interfaces/IRegistry.sol\\\";\\nimport \\\"../interfaces/IStakingBankStatic.sol\\\";\\n\\n/// @dev Main contract for all on-chain data.\\n/// Check `UmbrellaFeedsReader` to see how to integrate.\\n///\\n/// @notice This contract can be destroyed and replaced with new one (with new address).\\n/// For best gas efficiency you should pick one of two ways of integration:\\n/// 1. make `UmbrellaFeeds` immutable and use fallback in case of selfdestruct. After new deployment, it is recommended\\n/// to update address to avoid fallback and reduce gas cost to minimum. In long run this is most efficient solution,\\n/// better than any proxy.\\n/// 2. always check newest `UmbrellaFeeds` via `Regostry` and fallback will not be needed.\\ncontract UmbrellaFeeds is IUmbrellaFeeds {\\n bytes constant public ETH_PREFIX = \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\";\\n string constant public NAME = \\\"UmbrellaFeeds\\\";\\n\\n /// @dev deployment time, used for protect for unintentional destroy\\n uint256 public immutable DEPLOYED_AT; // solhint-disable-line var-name-mixedcase\\n\\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\\n /// resolve newest `UmbrellaFeeds` address\\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\\n\\n /// @dev StakingBank contract where list of validators is stored\\n IStakingBankStatic public immutable STAKING_BANK; // solhint-disable-line var-name-mixedcase\\n\\n /// @dev minimal number of signatures required for accepting price submission (PoA)\\n uint16 public immutable REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\\n\\n /// @dev decimals for prices stored in this contract\\n uint8 public immutable DECIMALS; // solhint-disable-line var-name-mixedcase\\n\\n /// @notice map of all prices stored in this contract, key for map is hash of feed name\\n /// eg for \\\"ETH-USD\\\" feed, key will be hash(\\\"ETH-USD\\\")\\n mapping (bytes32 => PriceData) private _prices;\\n\\n error ArraysDataDoNotMatch();\\n error FeedNotExist();\\n error NotEnoughSignatures();\\n error InvalidSigner();\\n error InvalidRequiredSignatures();\\n error SignaturesOutOfOrder();\\n error ECDSAInvalidSignatureS();\\n error ECDSAInvalidSignatureV();\\n error OldData();\\n error ContractInUse();\\n error ContractNotInitialised();\\n\\n /// @param _contractRegistry Registry address\\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\\n /// @param _decimals decimals for prices stored in this contract\\n constructor(\\n IRegistry _contractRegistry,\\n uint16 _requiredSignatures,\\n uint8 _decimals\\n ) {\\n if (_requiredSignatures == 0) revert InvalidRequiredSignatures();\\n\\n REGISTRY = _contractRegistry;\\n REQUIRED_SIGNATURES = _requiredSignatures;\\n STAKING_BANK = IStakingBankStatic(_contractRegistry.requireAndGetAddress(\\\"StakingBank\\\"));\\n DECIMALS = _decimals;\\n DEPLOYED_AT = block.timestamp;\\n }\\n\\n /// @dev destroys old contract\\n /// there is sanity check that prevents abuse of destroy method\\n /// @param _name string feed key to verify, that contract was initialised\\n function destroy(string calldata _name) external {\\n if (REGISTRY.getAddressByString(NAME) == address(this)) revert ContractInUse();\\n\\n if (_prices[keccak256(abi.encodePacked(_name))].timestamp == 0 && DEPLOYED_AT + 3 days > block.timestamp) {\\n revert ContractNotInitialised();\\n }\\n\\n selfdestruct(payable(msg.sender));\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function update(\\n bytes32[] calldata _priceKeys,\\n PriceData[] calldata _priceDatas,\\n Signature[] calldata _signatures\\n ) external {\\n if (_priceKeys.length != _priceDatas.length) revert ArraysDataDoNotMatch();\\n\\n bytes32 priceDataHash = keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\\n verifySignatures(priceDataHash, _signatures);\\n\\n uint256 i;\\n\\n while (i < _priceDatas.length) {\\n bytes32 priceKey = _priceKeys[i];\\n\\n // we do not allow for older prices\\n // at the same time it prevents from reusing signatures\\n if (_prices[priceKey].timestamp >= _priceDatas[i].timestamp) revert OldData();\\n\\n _prices[priceKey] = _priceDatas[i];\\n\\n // atm there is no need for events, so in order to save gas, we do not emit any\\n unchecked { i++; }\\n }\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\\n data = new PriceData[](_keys.length);\\n\\n for (uint256 i; i < _keys.length;) {\\n data[i] = _prices[_keys[i]];\\n if (data[i].timestamp == 0) revert FeedNotExist();\\n\\n unchecked { i++; }\\n }\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\\n data = new PriceData[](_keys.length);\\n\\n for (uint256 i; i < _keys.length;) {\\n data[i] = _prices[_keys[i]];\\n unchecked { i++; }\\n }\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function prices(bytes32 _key) external view returns (PriceData memory data) {\\n data = _prices[_key];\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getPriceData(bytes32 _key) external view returns (PriceData memory data) {\\n data = _prices[_key];\\n if (data.timestamp == 0) revert FeedNotExist();\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getPrice(bytes32 _key) external view returns (uint128 price) {\\n PriceData memory data = _prices[_key];\\n if (data.timestamp == 0) revert FeedNotExist();\\n\\n return data.price;\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp) {\\n PriceData memory data = _prices[_key];\\n if (data.timestamp == 0) revert FeedNotExist();\\n\\n return (data.price, data.timestamp);\\n }\\n\\n function getPriceTimestampHeartbeat(bytes32 _key)\\n external\\n view\\n returns (uint128 price, uint32 timestamp, uint24 heartbeat)\\n {\\n PriceData memory data = _prices[_key];\\n if (data.timestamp == 0) revert FeedNotExist();\\n\\n return (data.price, data.timestamp, data.heartbeat);\\n }\\n\\n /// @inheritdoc IUmbrellaFeeds\\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data) {\\n bytes32 key = keccak256(abi.encodePacked(_name));\\n data = _prices[key];\\n }\\n\\n /// @dev helper method for QA purposes\\n /// @return hash of data that are signed by validators (keys and priced data)\\n function hashData(bytes32[] calldata _priceKeys, PriceData[] calldata _priceDatas)\\n external\\n view\\n returns (bytes32)\\n {\\n return keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\\n }\\n\\n /// @param _hash hash of signed data\\n /// @param _signatures array of validators signatures\\n function verifySignatures(bytes32 _hash, Signature[] calldata _signatures) public view {\\n address prevSigner = address(0x0);\\n\\n if (_signatures.length < REQUIRED_SIGNATURES) revert NotEnoughSignatures();\\n\\n address[] memory validators = new address[](REQUIRED_SIGNATURES);\\n\\n // to save gas we check only required number of signatures\\n // case, where you can have part of signatures invalid but still enough valid in total is not supported\\n for (uint256 i; i < REQUIRED_SIGNATURES;) {\\n (uint8 v, bytes32 r, bytes32 s) = (_signatures[i].v, _signatures[i].r, _signatures[i].s);\\n\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n revert ECDSAInvalidSignatureS();\\n }\\n\\n if (uint8(v) != 27 && uint8(v) != 28) revert ECDSAInvalidSignatureV();\\n\\n address signer = recoverSigner(_hash, v, r, s);\\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\\n\\n // because we check only required number of signatures, any invalid one will cause revert\\n prevSigner = signer;\\n validators[i] = signer;\\n\\n unchecked { i++; }\\n }\\n\\n // bulk verification can optimise gas when we have 5 or more validators\\n if (!STAKING_BANK.verifyValidators(validators)) revert InvalidSigner();\\n }\\n\\n function getChainId() public view returns (uint256 id) {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n id := chainid()\\n }\\n }\\n\\n /// @param _hash hashed of data\\n /// @param _v part of signature\\n /// @param _r part of signature\\n /// @param _s part of signature\\n /// @return signer address\\n function recoverSigner(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _hash));\\n return ecrecover(hash, _v, _r, _s);\\n }\\n\\n /// @dev to follow Registrable interface\\n function getName() public pure returns (bytes32) {\\n return \\\"UmbrellaFeeds\\\";\\n }\\n}\\n\",\"keccak256\":\"0xf5dcfbbdfe5a5ed6e7579246363b10cdc0aa30580fec74025e0704c2b042d369\",\"license\":\"MIT\"}},\"version\":1}", "bytecode": "0x6101206040523480156200001257600080fd5b50604051620030a4380380620030a4833981810160405281019062000038919062000286565b60008261ffff160362000077576040517f458bb42100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff16815250508161ffff1660e08161ffff16815250508273ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b8152600401620000f49062000308565b602060405180830381865afa15801562000112573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000138919062000354565b73ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff16815250508060ff166101008160ff1681525050426080818152505050505062000386565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620001bd8262000190565b9050919050565b6000620001d182620001b0565b9050919050565b620001e381620001c4565b8114620001ef57600080fd5b50565b6000815190506200020381620001d8565b92915050565b600061ffff82169050919050565b620002228162000209565b81146200022e57600080fd5b50565b600081519050620002428162000217565b92915050565b600060ff82169050919050565b620002608162000248565b81146200026c57600080fd5b50565b600081519050620002808162000255565b92915050565b600080600060608486031215620002a257620002a16200018b565b5b6000620002b286828701620001f2565b9350506020620002c58682870162000231565b9250506040620002d8868287016200026f565b9150509250925092565b7f5374616b696e6742616e6b000000000000000000000000000000000000000000815250565b60006020820190506200031e60008301620002e2565b919050565b6200032e81620001b0565b81146200033a57600080fd5b50565b6000815190506200034e8162000323565b92915050565b6000602082840312156200036d576200036c6200018b565b5b60006200037d848285016200033d565b91505092915050565b60805160a05160c05160e05161010051612caf620003f560003960006108b10152600081816104e501528181610548015281816105ba01526116980152600081816107da01526116f501526000818161045e015261107e0152600081816111fd015261127a0152612caf6000f3fe608060405234801561001057600080fd5b50600436106101125760003560e01c806306433b1b1461011757806317d7de7c1461013557806324c89a491461015357806326559877146101715780632e0f26251461018d5780632e550693146101ab57806331d98b3f146101db5780633408e4701461020b578063385e05da1461022957806343fa6211146102595780635b38adc71461028957806360846bc6146102b95780636b9c3c7c146102e95780636ebb8cd2146103055780638a1194d31461032357806395f1cf301461035457806396594f66146103705780639ac18b19146103a2578063a3f4df7e146103c0578063c65a53ad146103de578063ccc6fd69146103fc578063d45167d01461042c575b600080fd5b61011f61045c565b60405161012c91906118df565b60405180910390f35b61013d610480565b60405161014a9190611913565b60405180910390f35b61015b6104a8565b60405161016891906119c7565b60405180910390f35b61018b60048036038101906101869190611a84565b6104e1565b005b6101956108af565b6040516101a29190611b00565b60405180910390f35b6101c560048036038101906101c09190611b71565b6108d3565b6040516101d29190611d39565b60405180910390f35b6101f560048036038101906101f09190611d5b565b610a54565b6040516102029190611d97565b60405180910390f35b610213610b77565b6040516102209190611dcb565b60405180910390f35b610243600480360381019061023e9190611b71565b610b7f565b6040516102509190611d39565b60405180910390f35b610273600480360381019061026e9190611d5b565b610d5e565b6040516102809190611e3b565b60405180910390f35b6102a3600480360381019061029e9190611eac565b610e7e565b6040516102b09190611e3b565b60405180910390f35b6102d360048036038101906102ce9190611d5b565b610f89565b6040516102e09190611e3b565b60405180910390f35b61030360048036038101906102fe9190611eac565b611065565b005b61030d611278565b60405161031a9190611dcb565b60405180910390f35b61033d60048036038101906103389190611d5b565b61129c565b60405161034b929190611f08565b60405180910390f35b61036e60048036038101906103699190611f87565b6113c8565b005b61038a60048036038101906103859190611d5b565b611560565b6040516103999392919061204a565b60405180910390f35b6103aa611696565b6040516103b7919061209e565b60405180910390f35b6103c86116ba565b6040516103d5919061210e565b60405180910390f35b6103e66116f3565b6040516103f39190612151565b60405180910390f35b6104166004803603810190610411919061216c565b611717565b6040516104239190611913565b60405180910390f35b61044660048036038101906104419190612219565b61175b565b60405161045391906122a1565b60405180910390f35b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f556d6272656c6c61466565647300000000000000000000000000000000000000905090565b6040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525081565b60007f000000000000000000000000000000000000000000000000000000000000000061ffff16838390501015610544576040517fe246dc6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000061ffff1667ffffffffffffffff811115610584576105836122bc565b5b6040519080825280602002602001820160405280156105b25781602001602082028036833780820191505090505b50905060005b7f000000000000000000000000000000000000000000000000000000000000000061ffff168110156107d75760008060008787858181106105fc576105fb6122eb565b5b9050606002016000016020810190610614919061231a565b888886818110610627576106266122eb565b5b90506060020160200135898987818110610644576106436122eb565b5b905060600201604001359250925092507f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08160001c11156106b1576040517f454ffaa700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601b8360ff16141580156106c95750601c8360ff1614155b15610700576040517f1afa741400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061070e8a85858561175b565b90508073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1610610775576040517f9079f69b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8096508086868151811061078c5761078b6122eb565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508480600101955050505050506105b8565b507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16631d4f9ce0826040518263ffffffff1660e01b81526004016108319190612405565b602060405180830381865afa15801561084e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610872919061245f565b6108a8576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60608282905067ffffffffffffffff8111156108f2576108f16122bc565b5b60405190808252806020026020018201604052801561092b57816020015b610918611818565b8152602001906001900390816109105790505b50905060005b83839050811015610a4d57600080858584818110610952576109516122eb565b5b9050602002013581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681525050828281518110610a3557610a346122eb565b5b60200260200101819052508080600101915050610931565b5092915050565b6000806000808481526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603610b6a576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060600151915050919050565b600046905090565b60608282905067ffffffffffffffff811115610b9e57610b9d6122bc565b5b604051908082528060200260200182016040528015610bd757816020015b610bc4611818565b815260200190600190039081610bbc5790505b50905060005b83839050811015610d5757600080858584818110610bfe57610bfd6122eb565b5b9050602002013581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681525050828281518110610ce157610ce06122eb565b5b60200260200101819052506000828281518110610d0157610d006122eb565b5b60200260200101516040015163ffffffff1603610d4a576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8080600101915050610bdd565b5092915050565b610d66611818565b6000808381526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603610e79576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b610e86611818565b60008383604051602001610e9b9291906124cb565b6040516020818303038152906040528051906020012090506000808281526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505091505092915050565b610f91611818565b6000808381526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815250509050919050565b3073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663e8f98f886040518060400160405280600d81526020017f556d6272656c6c614665656473000000000000000000000000000000000000008152506040518263ffffffff1660e01b815260040161110a919061210e565b602060405180830381865afa158015611127573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114b9190612510565b73ffffffffffffffffffffffffffffffffffffffff1603611198576040517f8c3e700900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600084846040516020016111b09291906124cb565b60405160208183030381529060405280519060200120815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff161480156112285750426203f4807f0000000000000000000000000000000000000000000000000000000000000000611226919061256c565b115b1561125f576040517fcf51b43b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff16ff5b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060008060008581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff16036113b4576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806060015181604001519250925050915091565b838390508686905014611407576040517f0cf7902300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611411610b77565b308888888860405160200161142b96959493929190612820565b60405160208183030381529060405280519060200120905061144e8184846104e1565b60005b85859050811015611556576000888883818110611471576114706122eb565b5b90506020020135905086868381811061148d5761148c6122eb565b5b90506080020160400160208101906114a59190612877565b63ffffffff1660008083815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff161061150e576040517f1251b2f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b868683818110611521576115206122eb565b5b90506080020160008083815260200190815260200160002081816115459190612ba1565b905050818060010192505050611451565b5050505050505050565b6000806000806000808681526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603611679576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806060015181604001518260200151935093509350509193909250565b7f000000000000000000000000000000000000000000000000000000000000000081565b6040518060400160405280600d81526020017f556d6272656c6c6146656564730000000000000000000000000000000000000081525081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000611721610b77565b308686868660405160200161173b96959493929190612820565b604051602081830303815290604052805190602001209050949350505050565b6000806040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250866040516020016117a6929190612c0c565b604051602081830303815290604052805190602001209050600181868686604051600081526020016040526040516117e19493929190612c34565b6020604051602081039080840390855afa158015611803573d6000803e3d6000fd5b50505060206040510351915050949350505050565b6040518060800160405280600060ff168152602001600062ffffff168152602001600063ffffffff16815260200160006fffffffffffffffffffffffffffffffff1681525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006118a56118a061189b84611860565b611880565b611860565b9050919050565b60006118b78261188a565b9050919050565b60006118c9826118ac565b9050919050565b6118d9816118be565b82525050565b60006020820190506118f460008301846118d0565b92915050565b6000819050919050565b61190d816118fa565b82525050565b60006020820190506119286000830184611904565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561196857808201518184015260208101905061194d565b83811115611977576000848401525b50505050565b6000601f19601f8301169050919050565b60006119998261192e565b6119a38185611939565b93506119b381856020860161194a565b6119bc8161197d565b840191505092915050565b600060208201905081810360008301526119e1818461198e565b905092915050565b600080fd5b600080fd5b6119fc816118fa565b8114611a0757600080fd5b50565b600081359050611a19816119f3565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112611a4457611a43611a1f565b5b8235905067ffffffffffffffff811115611a6157611a60611a24565b5b602083019150836060820283011115611a7d57611a7c611a29565b5b9250929050565b600080600060408486031215611a9d57611a9c6119e9565b5b6000611aab86828701611a0a565b935050602084013567ffffffffffffffff811115611acc57611acb6119ee565b5b611ad886828701611a2e565b92509250509250925092565b600060ff82169050919050565b611afa81611ae4565b82525050565b6000602082019050611b156000830184611af1565b92915050565b60008083601f840112611b3157611b30611a1f565b5b8235905067ffffffffffffffff811115611b4e57611b4d611a24565b5b602083019150836020820283011115611b6a57611b69611a29565b5b9250929050565b60008060208385031215611b8857611b876119e9565b5b600083013567ffffffffffffffff811115611ba657611ba56119ee565b5b611bb285828601611b1b565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b611bf381611ae4565b82525050565b600062ffffff82169050919050565b611c1181611bf9565b82525050565b600063ffffffff82169050919050565b611c3081611c17565b82525050565b60006fffffffffffffffffffffffffffffffff82169050919050565b611c5b81611c36565b82525050565b608082016000820151611c776000850182611bea565b506020820151611c8a6020850182611c08565b506040820151611c9d6040850182611c27565b506060820151611cb06060850182611c52565b50505050565b6000611cc28383611c61565b60808301905092915050565b6000602082019050919050565b6000611ce682611bbe565b611cf08185611bc9565b9350611cfb83611bda565b8060005b83811015611d2c578151611d138882611cb6565b9750611d1e83611cce565b925050600181019050611cff565b5085935050505092915050565b60006020820190508181036000830152611d538184611cdb565b905092915050565b600060208284031215611d7157611d706119e9565b5b6000611d7f84828501611a0a565b91505092915050565b611d9181611c36565b82525050565b6000602082019050611dac6000830184611d88565b92915050565b6000819050919050565b611dc581611db2565b82525050565b6000602082019050611de06000830184611dbc565b92915050565b608082016000820151611dfc6000850182611bea565b506020820151611e0f6020850182611c08565b506040820151611e226040850182611c27565b506060820151611e356060850182611c52565b50505050565b6000608082019050611e506000830184611de6565b92915050565b60008083601f840112611e6c57611e6b611a1f565b5b8235905067ffffffffffffffff811115611e8957611e88611a24565b5b602083019150836001820283011115611ea557611ea4611a29565b5b9250929050565b60008060208385031215611ec357611ec26119e9565b5b600083013567ffffffffffffffff811115611ee157611ee06119ee565b5b611eed85828601611e56565b92509250509250929050565b611f0281611c17565b82525050565b6000604082019050611f1d6000830185611d88565b611f2a6020830184611ef9565b9392505050565b60008083601f840112611f4757611f46611a1f565b5b8235905067ffffffffffffffff811115611f6457611f63611a24565b5b602083019150836080820283011115611f8057611f7f611a29565b5b9250929050565b60008060008060008060608789031215611fa457611fa36119e9565b5b600087013567ffffffffffffffff811115611fc257611fc16119ee565b5b611fce89828a01611b1b565b9650965050602087013567ffffffffffffffff811115611ff157611ff06119ee565b5b611ffd89828a01611f31565b9450945050604087013567ffffffffffffffff8111156120205761201f6119ee565b5b61202c89828a01611a2e565b92509250509295509295509295565b61204481611bf9565b82525050565b600060608201905061205f6000830186611d88565b61206c6020830185611ef9565b612079604083018461203b565b949350505050565b600061ffff82169050919050565b61209881612081565b82525050565b60006020820190506120b3600083018461208f565b92915050565b600081519050919050565b600082825260208201905092915050565b60006120e0826120b9565b6120ea81856120c4565b93506120fa81856020860161194a565b6121038161197d565b840191505092915050565b6000602082019050818103600083015261212881846120d5565b905092915050565b600061213b826118ac565b9050919050565b61214b81612130565b82525050565b60006020820190506121666000830184612142565b92915050565b60008060008060408587031215612186576121856119e9565b5b600085013567ffffffffffffffff8111156121a4576121a36119ee565b5b6121b087828801611b1b565b9450945050602085013567ffffffffffffffff8111156121d3576121d26119ee565b5b6121df87828801611f31565b925092505092959194509250565b6121f681611ae4565b811461220157600080fd5b50565b600081359050612213816121ed565b92915050565b60008060008060808587031215612233576122326119e9565b5b600061224187828801611a0a565b945050602061225287828801612204565b935050604061226387828801611a0a565b925050606061227487828801611a0a565b91505092959194509250565b600061228b82611860565b9050919050565b61229b81612280565b82525050565b60006020820190506122b66000830184612292565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156123305761232f6119e9565b5b600061233e84828501612204565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61237c81612280565b82525050565b600061238e8383612373565b60208301905092915050565b6000602082019050919050565b60006123b282612347565b6123bc8185612352565b93506123c783612363565b8060005b838110156123f85781516123df8882612382565b97506123ea8361239a565b9250506001810190506123cb565b5085935050505092915050565b6000602082019050818103600083015261241f81846123a7565b905092915050565b60008115159050919050565b61243c81612427565b811461244757600080fd5b50565b60008151905061245981612433565b92915050565b600060208284031215612475576124746119e9565b5b60006124838482850161244a565b91505092915050565b600081905092915050565b82818337600083830152505050565b60006124b2838561248c565b93506124bf838584612497565b82840190509392505050565b60006124d88284866124a6565b91508190509392505050565b6124ed81612280565b81146124f857600080fd5b50565b60008151905061250a816124e4565b92915050565b600060208284031215612526576125256119e9565b5b6000612534848285016124fb565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061257782611db2565b915061258283611db2565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156125b7576125b661253d565b5b828201905092915050565b600082825260208201905092915050565b600080fd5b60006125e483856125c2565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115612617576126166125d3565b5b602083029250612628838584612497565b82840190509392505050565b6000819050919050565b600061264d6020840184612204565b905092915050565b61265e81611bf9565b811461266957600080fd5b50565b60008135905061267b81612655565b92915050565b6000612690602084018461266c565b905092915050565b6126a181611c17565b81146126ac57600080fd5b50565b6000813590506126be81612698565b92915050565b60006126d360208401846126af565b905092915050565b6126e481611c36565b81146126ef57600080fd5b50565b600081359050612701816126db565b92915050565b600061271660208401846126f2565b905092915050565b6080820161272f600083018361263e565b61273c6000850182611bea565b5061274a6020830183612681565b6127576020850182611c08565b5061276560408301836126c4565b6127726040850182611c27565b506127806060830183612707565b61278d6060850182611c52565b50505050565b600061279f838361271e565b60808301905092915050565b600082905092915050565b6000608082019050919050565b60006127cf8385611bc9565b93506127da82612634565b8060005b85811015612813576127f082846127ab565b6127fa8882612793565b9750612805836127b6565b9250506001810190506127de565b5085925050509392505050565b60006080820190506128356000830189611dbc565b6128426020830188612292565b81810360408301526128558186886125d8565b9050818103606083015261286a8184866127c3565b9050979650505050505050565b60006020828403121561288d5761288c6119e9565b5b600061289b848285016126af565b91505092915050565b600081356128b1816121ed565b80915050919050565b60008160001b9050919050565b600060ff6128d4846128ba565b9350801983169250808416831791505092915050565b60006129056129006128fb84611ae4565b611880565b611ae4565b9050919050565b6000819050919050565b61291f826128ea565b61293261292b8261290c565b83546128c7565b8255505050565b6000813561294681612655565b80915050919050565b60008160081b9050919050565b600063ffffff0061296c8461294f565b9350801983169250808416831791505092915050565b600061299d61299861299384611bf9565b611880565b611bf9565b9050919050565b6000819050919050565b6129b782612982565b6129ca6129c3826129a4565b835461295c565b8255505050565b600081356129de81612698565b80915050919050565b60008160201b9050919050565b600067ffffffff00000000612a08846129e7565b9350801983169250808416831791505092915050565b6000612a39612a34612a2f84611c17565b611880565b611c17565b9050919050565b6000819050919050565b612a5382612a1e565b612a66612a5f82612a40565b83546129f4565b8255505050565b60008135612a7a816126db565b80915050919050565b60008160401b9050919050565b600077ffffffffffffffffffffffffffffffff0000000000000000612ab484612a83565b9350801983169250808416831791505092915050565b6000612ae5612ae0612adb84611c36565b611880565b611c36565b9050919050565b6000819050919050565b612aff82612aca565b612b12612b0b82612aec565b8354612a90565b8255505050565b600081016000830180612b2b816128a4565b9050612b378184612916565b505050600081016020830180612b4c81612939565b9050612b5881846129ae565b505050600081016040830180612b6d816129d1565b9050612b798184612a4a565b505050600081016060830180612b8e81612a6d565b9050612b9a8184612af6565b5050505050565b612bab8282612b19565b5050565b600081905092915050565b6000612bc58261192e565b612bcf8185612baf565b9350612bdf81856020860161194a565b80840191505092915050565b6000819050919050565b612c06612c01826118fa565b612beb565b82525050565b6000612c188285612bba565b9150612c248284612bf5565b6020820191508190509392505050565b6000608082019050612c496000830187611904565b612c566020830186611af1565b612c636040830185611904565b612c706060830184611904565b9594505050505056fea26469706673582212204e20478e2e3070a20aa83127753a448e1b78b26fd4b44673d2f1b4027a2cf6be64736f6c634300080d0033", "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101125760003560e01c806306433b1b1461011757806317d7de7c1461013557806324c89a491461015357806326559877146101715780632e0f26251461018d5780632e550693146101ab57806331d98b3f146101db5780633408e4701461020b578063385e05da1461022957806343fa6211146102595780635b38adc71461028957806360846bc6146102b95780636b9c3c7c146102e95780636ebb8cd2146103055780638a1194d31461032357806395f1cf301461035457806396594f66146103705780639ac18b19146103a2578063a3f4df7e146103c0578063c65a53ad146103de578063ccc6fd69146103fc578063d45167d01461042c575b600080fd5b61011f61045c565b60405161012c91906118df565b60405180910390f35b61013d610480565b60405161014a9190611913565b60405180910390f35b61015b6104a8565b60405161016891906119c7565b60405180910390f35b61018b60048036038101906101869190611a84565b6104e1565b005b6101956108af565b6040516101a29190611b00565b60405180910390f35b6101c560048036038101906101c09190611b71565b6108d3565b6040516101d29190611d39565b60405180910390f35b6101f560048036038101906101f09190611d5b565b610a54565b6040516102029190611d97565b60405180910390f35b610213610b77565b6040516102209190611dcb565b60405180910390f35b610243600480360381019061023e9190611b71565b610b7f565b6040516102509190611d39565b60405180910390f35b610273600480360381019061026e9190611d5b565b610d5e565b6040516102809190611e3b565b60405180910390f35b6102a3600480360381019061029e9190611eac565b610e7e565b6040516102b09190611e3b565b60405180910390f35b6102d360048036038101906102ce9190611d5b565b610f89565b6040516102e09190611e3b565b60405180910390f35b61030360048036038101906102fe9190611eac565b611065565b005b61030d611278565b60405161031a9190611dcb565b60405180910390f35b61033d60048036038101906103389190611d5b565b61129c565b60405161034b929190611f08565b60405180910390f35b61036e60048036038101906103699190611f87565b6113c8565b005b61038a60048036038101906103859190611d5b565b611560565b6040516103999392919061204a565b60405180910390f35b6103aa611696565b6040516103b7919061209e565b60405180910390f35b6103c86116ba565b6040516103d5919061210e565b60405180910390f35b6103e66116f3565b6040516103f39190612151565b60405180910390f35b6104166004803603810190610411919061216c565b611717565b6040516104239190611913565b60405180910390f35b61044660048036038101906104419190612219565b61175b565b60405161045391906122a1565b60405180910390f35b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f556d6272656c6c61466565647300000000000000000000000000000000000000905090565b6040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525081565b60007f000000000000000000000000000000000000000000000000000000000000000061ffff16838390501015610544576040517fe246dc6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000061ffff1667ffffffffffffffff811115610584576105836122bc565b5b6040519080825280602002602001820160405280156105b25781602001602082028036833780820191505090505b50905060005b7f000000000000000000000000000000000000000000000000000000000000000061ffff168110156107d75760008060008787858181106105fc576105fb6122eb565b5b9050606002016000016020810190610614919061231a565b888886818110610627576106266122eb565b5b90506060020160200135898987818110610644576106436122eb565b5b905060600201604001359250925092507f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08160001c11156106b1576040517f454ffaa700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601b8360ff16141580156106c95750601c8360ff1614155b15610700576040517f1afa741400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061070e8a85858561175b565b90508073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1610610775576040517f9079f69b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8096508086868151811061078c5761078b6122eb565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508480600101955050505050506105b8565b507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16631d4f9ce0826040518263ffffffff1660e01b81526004016108319190612405565b602060405180830381865afa15801561084e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610872919061245f565b6108a8576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60608282905067ffffffffffffffff8111156108f2576108f16122bc565b5b60405190808252806020026020018201604052801561092b57816020015b610918611818565b8152602001906001900390816109105790505b50905060005b83839050811015610a4d57600080858584818110610952576109516122eb565b5b9050602002013581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681525050828281518110610a3557610a346122eb565b5b60200260200101819052508080600101915050610931565b5092915050565b6000806000808481526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603610b6a576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060600151915050919050565b600046905090565b60608282905067ffffffffffffffff811115610b9e57610b9d6122bc565b5b604051908082528060200260200182016040528015610bd757816020015b610bc4611818565b815260200190600190039081610bbc5790505b50905060005b83839050811015610d5757600080858584818110610bfe57610bfd6122eb565b5b9050602002013581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681525050828281518110610ce157610ce06122eb565b5b60200260200101819052506000828281518110610d0157610d006122eb565b5b60200260200101516040015163ffffffff1603610d4a576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8080600101915050610bdd565b5092915050565b610d66611818565b6000808381526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603610e79576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b610e86611818565b60008383604051602001610e9b9291906124cb565b6040516020818303038152906040528051906020012090506000808281526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505091505092915050565b610f91611818565b6000808381526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815250509050919050565b3073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663e8f98f886040518060400160405280600d81526020017f556d6272656c6c614665656473000000000000000000000000000000000000008152506040518263ffffffff1660e01b815260040161110a919061210e565b602060405180830381865afa158015611127573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114b9190612510565b73ffffffffffffffffffffffffffffffffffffffff1603611198576040517f8c3e700900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600084846040516020016111b09291906124cb565b60405160208183030381529060405280519060200120815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff161480156112285750426203f4807f0000000000000000000000000000000000000000000000000000000000000000611226919061256c565b115b1561125f576040517fcf51b43b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff16ff5b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060008060008581526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff16036113b4576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806060015181604001519250925050915091565b838390508686905014611407576040517f0cf7902300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611411610b77565b308888888860405160200161142b96959493929190612820565b60405160208183030381529060405280519060200120905061144e8184846104e1565b60005b85859050811015611556576000888883818110611471576114706122eb565b5b90506020020135905086868381811061148d5761148c6122eb565b5b90506080020160400160208101906114a59190612877565b63ffffffff1660008083815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff161061150e576040517f1251b2f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b868683818110611521576115206122eb565b5b90506080020160008083815260200190815260200160002081816115459190612ba1565b905050818060010192505050611451565b5050505050505050565b6000806000806000808681526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152505090506000816040015163ffffffff1603611679576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806060015181604001518260200151935093509350509193909250565b7f000000000000000000000000000000000000000000000000000000000000000081565b6040518060400160405280600d81526020017f556d6272656c6c6146656564730000000000000000000000000000000000000081525081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000611721610b77565b308686868660405160200161173b96959493929190612820565b604051602081830303815290604052805190602001209050949350505050565b6000806040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250866040516020016117a6929190612c0c565b604051602081830303815290604052805190602001209050600181868686604051600081526020016040526040516117e19493929190612c34565b6020604051602081039080840390855afa158015611803573d6000803e3d6000fd5b50505060206040510351915050949350505050565b6040518060800160405280600060ff168152602001600062ffffff168152602001600063ffffffff16815260200160006fffffffffffffffffffffffffffffffff1681525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006118a56118a061189b84611860565b611880565b611860565b9050919050565b60006118b78261188a565b9050919050565b60006118c9826118ac565b9050919050565b6118d9816118be565b82525050565b60006020820190506118f460008301846118d0565b92915050565b6000819050919050565b61190d816118fa565b82525050565b60006020820190506119286000830184611904565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561196857808201518184015260208101905061194d565b83811115611977576000848401525b50505050565b6000601f19601f8301169050919050565b60006119998261192e565b6119a38185611939565b93506119b381856020860161194a565b6119bc8161197d565b840191505092915050565b600060208201905081810360008301526119e1818461198e565b905092915050565b600080fd5b600080fd5b6119fc816118fa565b8114611a0757600080fd5b50565b600081359050611a19816119f3565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112611a4457611a43611a1f565b5b8235905067ffffffffffffffff811115611a6157611a60611a24565b5b602083019150836060820283011115611a7d57611a7c611a29565b5b9250929050565b600080600060408486031215611a9d57611a9c6119e9565b5b6000611aab86828701611a0a565b935050602084013567ffffffffffffffff811115611acc57611acb6119ee565b5b611ad886828701611a2e565b92509250509250925092565b600060ff82169050919050565b611afa81611ae4565b82525050565b6000602082019050611b156000830184611af1565b92915050565b60008083601f840112611b3157611b30611a1f565b5b8235905067ffffffffffffffff811115611b4e57611b4d611a24565b5b602083019150836020820283011115611b6a57611b69611a29565b5b9250929050565b60008060208385031215611b8857611b876119e9565b5b600083013567ffffffffffffffff811115611ba657611ba56119ee565b5b611bb285828601611b1b565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b611bf381611ae4565b82525050565b600062ffffff82169050919050565b611c1181611bf9565b82525050565b600063ffffffff82169050919050565b611c3081611c17565b82525050565b60006fffffffffffffffffffffffffffffffff82169050919050565b611c5b81611c36565b82525050565b608082016000820151611c776000850182611bea565b506020820151611c8a6020850182611c08565b506040820151611c9d6040850182611c27565b506060820151611cb06060850182611c52565b50505050565b6000611cc28383611c61565b60808301905092915050565b6000602082019050919050565b6000611ce682611bbe565b611cf08185611bc9565b9350611cfb83611bda565b8060005b83811015611d2c578151611d138882611cb6565b9750611d1e83611cce565b925050600181019050611cff565b5085935050505092915050565b60006020820190508181036000830152611d538184611cdb565b905092915050565b600060208284031215611d7157611d706119e9565b5b6000611d7f84828501611a0a565b91505092915050565b611d9181611c36565b82525050565b6000602082019050611dac6000830184611d88565b92915050565b6000819050919050565b611dc581611db2565b82525050565b6000602082019050611de06000830184611dbc565b92915050565b608082016000820151611dfc6000850182611bea565b506020820151611e0f6020850182611c08565b506040820151611e226040850182611c27565b506060820151611e356060850182611c52565b50505050565b6000608082019050611e506000830184611de6565b92915050565b60008083601f840112611e6c57611e6b611a1f565b5b8235905067ffffffffffffffff811115611e8957611e88611a24565b5b602083019150836001820283011115611ea557611ea4611a29565b5b9250929050565b60008060208385031215611ec357611ec26119e9565b5b600083013567ffffffffffffffff811115611ee157611ee06119ee565b5b611eed85828601611e56565b92509250509250929050565b611f0281611c17565b82525050565b6000604082019050611f1d6000830185611d88565b611f2a6020830184611ef9565b9392505050565b60008083601f840112611f4757611f46611a1f565b5b8235905067ffffffffffffffff811115611f6457611f63611a24565b5b602083019150836080820283011115611f8057611f7f611a29565b5b9250929050565b60008060008060008060608789031215611fa457611fa36119e9565b5b600087013567ffffffffffffffff811115611fc257611fc16119ee565b5b611fce89828a01611b1b565b9650965050602087013567ffffffffffffffff811115611ff157611ff06119ee565b5b611ffd89828a01611f31565b9450945050604087013567ffffffffffffffff8111156120205761201f6119ee565b5b61202c89828a01611a2e565b92509250509295509295509295565b61204481611bf9565b82525050565b600060608201905061205f6000830186611d88565b61206c6020830185611ef9565b612079604083018461203b565b949350505050565b600061ffff82169050919050565b61209881612081565b82525050565b60006020820190506120b3600083018461208f565b92915050565b600081519050919050565b600082825260208201905092915050565b60006120e0826120b9565b6120ea81856120c4565b93506120fa81856020860161194a565b6121038161197d565b840191505092915050565b6000602082019050818103600083015261212881846120d5565b905092915050565b600061213b826118ac565b9050919050565b61214b81612130565b82525050565b60006020820190506121666000830184612142565b92915050565b60008060008060408587031215612186576121856119e9565b5b600085013567ffffffffffffffff8111156121a4576121a36119ee565b5b6121b087828801611b1b565b9450945050602085013567ffffffffffffffff8111156121d3576121d26119ee565b5b6121df87828801611f31565b925092505092959194509250565b6121f681611ae4565b811461220157600080fd5b50565b600081359050612213816121ed565b92915050565b60008060008060808587031215612233576122326119e9565b5b600061224187828801611a0a565b945050602061225287828801612204565b935050604061226387828801611a0a565b925050606061227487828801611a0a565b91505092959194509250565b600061228b82611860565b9050919050565b61229b81612280565b82525050565b60006020820190506122b66000830184612292565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156123305761232f6119e9565b5b600061233e84828501612204565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61237c81612280565b82525050565b600061238e8383612373565b60208301905092915050565b6000602082019050919050565b60006123b282612347565b6123bc8185612352565b93506123c783612363565b8060005b838110156123f85781516123df8882612382565b97506123ea8361239a565b9250506001810190506123cb565b5085935050505092915050565b6000602082019050818103600083015261241f81846123a7565b905092915050565b60008115159050919050565b61243c81612427565b811461244757600080fd5b50565b60008151905061245981612433565b92915050565b600060208284031215612475576124746119e9565b5b60006124838482850161244a565b91505092915050565b600081905092915050565b82818337600083830152505050565b60006124b2838561248c565b93506124bf838584612497565b82840190509392505050565b60006124d88284866124a6565b91508190509392505050565b6124ed81612280565b81146124f857600080fd5b50565b60008151905061250a816124e4565b92915050565b600060208284031215612526576125256119e9565b5b6000612534848285016124fb565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061257782611db2565b915061258283611db2565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156125b7576125b661253d565b5b828201905092915050565b600082825260208201905092915050565b600080fd5b60006125e483856125c2565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115612617576126166125d3565b5b602083029250612628838584612497565b82840190509392505050565b6000819050919050565b600061264d6020840184612204565b905092915050565b61265e81611bf9565b811461266957600080fd5b50565b60008135905061267b81612655565b92915050565b6000612690602084018461266c565b905092915050565b6126a181611c17565b81146126ac57600080fd5b50565b6000813590506126be81612698565b92915050565b60006126d360208401846126af565b905092915050565b6126e481611c36565b81146126ef57600080fd5b50565b600081359050612701816126db565b92915050565b600061271660208401846126f2565b905092915050565b6080820161272f600083018361263e565b61273c6000850182611bea565b5061274a6020830183612681565b6127576020850182611c08565b5061276560408301836126c4565b6127726040850182611c27565b506127806060830183612707565b61278d6060850182611c52565b50505050565b600061279f838361271e565b60808301905092915050565b600082905092915050565b6000608082019050919050565b60006127cf8385611bc9565b93506127da82612634565b8060005b85811015612813576127f082846127ab565b6127fa8882612793565b9750612805836127b6565b9250506001810190506127de565b5085925050509392505050565b60006080820190506128356000830189611dbc565b6128426020830188612292565b81810360408301526128558186886125d8565b9050818103606083015261286a8184866127c3565b9050979650505050505050565b60006020828403121561288d5761288c6119e9565b5b600061289b848285016126af565b91505092915050565b600081356128b1816121ed565b80915050919050565b60008160001b9050919050565b600060ff6128d4846128ba565b9350801983169250808416831791505092915050565b60006129056129006128fb84611ae4565b611880565b611ae4565b9050919050565b6000819050919050565b61291f826128ea565b61293261292b8261290c565b83546128c7565b8255505050565b6000813561294681612655565b80915050919050565b60008160081b9050919050565b600063ffffff0061296c8461294f565b9350801983169250808416831791505092915050565b600061299d61299861299384611bf9565b611880565b611bf9565b9050919050565b6000819050919050565b6129b782612982565b6129ca6129c3826129a4565b835461295c565b8255505050565b600081356129de81612698565b80915050919050565b60008160201b9050919050565b600067ffffffff00000000612a08846129e7565b9350801983169250808416831791505092915050565b6000612a39612a34612a2f84611c17565b611880565b611c17565b9050919050565b6000819050919050565b612a5382612a1e565b612a66612a5f82612a40565b83546129f4565b8255505050565b60008135612a7a816126db565b80915050919050565b60008160401b9050919050565b600077ffffffffffffffffffffffffffffffff0000000000000000612ab484612a83565b9350801983169250808416831791505092915050565b6000612ae5612ae0612adb84611c36565b611880565b611c36565b9050919050565b6000819050919050565b612aff82612aca565b612b12612b0b82612aec565b8354612a90565b8255505050565b600081016000830180612b2b816128a4565b9050612b378184612916565b505050600081016020830180612b4c81612939565b9050612b5881846129ae565b505050600081016040830180612b6d816129d1565b9050612b798184612a4a565b505050600081016060830180612b8e81612a6d565b9050612b9a8184612af6565b5050505050565b612bab8282612b19565b5050565b600081905092915050565b6000612bc58261192e565b612bcf8185612baf565b9350612bdf81856020860161194a565b80840191505092915050565b6000819050919050565b612c06612c01826118fa565b612beb565b82525050565b6000612c188285612bba565b9150612c248284612bf5565b6020820191508190509392505050565b6000608082019050612c496000830187611904565b612c566020830186611af1565b612c636040830185611904565b612c706060830184611904565b9594505050505056fea26469706673582212204e20478e2e3070a20aa83127753a448e1b78b26fd4b44673d2f1b4027a2cf6be64736f6c634300080d0033", @@ -858,12 +858,12 @@ "storageLayout": { "storage": [ { - "astId": 4270, + "astId": 4239, "contract": "contracts/onChainFeeds/UmbrellaFeeds.sol:UmbrellaFeeds", "label": "_prices", "offset": 0, "slot": "0", - "type": "t_mapping(t_bytes32,t_struct(PriceData)3396_storage)" + "type": "t_mapping(t_bytes32,t_struct(PriceData)3365_storage)" } ], "types": { @@ -872,19 +872,19 @@ "label": "bytes32", "numberOfBytes": "32" }, - "t_mapping(t_bytes32,t_struct(PriceData)3396_storage)": { + "t_mapping(t_bytes32,t_struct(PriceData)3365_storage)": { "encoding": "mapping", "key": "t_bytes32", "label": "mapping(bytes32 => struct IUmbrellaFeeds.PriceData)", "numberOfBytes": "32", - "value": "t_struct(PriceData)3396_storage" + "value": "t_struct(PriceData)3365_storage" }, - "t_struct(PriceData)3396_storage": { + "t_struct(PriceData)3365_storage": { "encoding": "inplace", "label": "struct IUmbrellaFeeds.PriceData", "members": [ { - "astId": 3386, + "astId": 3355, "contract": "contracts/onChainFeeds/UmbrellaFeeds.sol:UmbrellaFeeds", "label": "data", "offset": 0, @@ -892,7 +892,7 @@ "type": "t_uint8" }, { - "astId": 3389, + "astId": 3358, "contract": "contracts/onChainFeeds/UmbrellaFeeds.sol:UmbrellaFeeds", "label": "heartbeat", "offset": 1, @@ -900,7 +900,7 @@ "type": "t_uint24" }, { - "astId": 3392, + "astId": 3361, "contract": "contracts/onChainFeeds/UmbrellaFeeds.sol:UmbrellaFeeds", "label": "timestamp", "offset": 4, @@ -908,7 +908,7 @@ "type": "t_uint32" }, { - "astId": 3395, + "astId": 3364, "contract": "contracts/onChainFeeds/UmbrellaFeeds.sol:UmbrellaFeeds", "label": "price", "offset": 8, diff --git a/deployments/rootstock_production/solcInputs/dc68422c0ad35a4fe46d461b096b9383.json b/deployments/rootstock_production/solcInputs/dc68422c0ad35a4fe46d461b096b9383.json new file mode 100644 index 00000000..43238985 --- /dev/null +++ b/deployments/rootstock_production/solcInputs/dc68422c0ad35a4fe46d461b096b9383.json @@ -0,0 +1,125 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n }\n _balances[to] += amount;\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n _balances[account] += amount;\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n }\n _totalSupply -= amount;\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Trees proofs.\n *\n * The proofs can be generated using the JavaScript library\n * https://github.com/miguelmota/merkletreejs[merkletreejs].\n * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.\n *\n * See `test/utils/cryptography/MerkleProof.test.js` for some examples.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(\n bytes32[] memory proof,\n bytes32 root,\n bytes32 leaf\n ) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n bytes32 proofElement = proof[i];\n if (computedHash <= proofElement) {\n // Hash(current computed hash + current element of the proof)\n computedHash = _efficientHash(computedHash, proofElement);\n } else {\n // Hash(current element of the proof + current computed hash)\n computedHash = _efficientHash(proofElement, computedHash);\n }\n }\n return computedHash;\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "@umb-network/toolbox/dist/contracts/lib/ValueDecoder.sol": { + "content": "//SPDX-License-Identifier: Unlicensed\npragma solidity >=0.6.8;\n\nlibrary ValueDecoder {\n function toUint(bytes memory _bytes) internal pure returns (uint256 value) {\n assembly {\n value := mload(add(_bytes, 32))\n }\n }\n\n function toUint(bytes32 _bytes) internal pure returns (uint256 value) {\n assembly {\n value := _bytes\n }\n }\n\n function toInt(uint224 u) internal pure returns (int256) {\n int224 i;\n uint224 max = type(uint224).max;\n\n if (u <= (max - 1) / 2) { // positive values\n assembly {\n i := add(u, 0)\n }\n\n return i;\n } else { // negative values\n assembly {\n i := sub(sub(u, max), 1)\n }\n }\n\n return i;\n }\n}\n\n" + }, + "contracts/BaseChain.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\";\nimport \"@umb-network/toolbox/dist/contracts/lib/ValueDecoder.sol\";\n\nimport \"./interfaces/IBaseChainV1.sol\";\nimport \"./interfaces/IStakingBank.sol\";\nimport \"./extensions/Registrable.sol\";\nimport \"./Registry.sol\";\n\nabstract contract BaseChain is Registrable, Ownable {\n using ValueDecoder for bytes;\n using ValueDecoder for uint224;\n using MerkleProof for bytes32[];\n\n /// @param root merkle root for consensus\n /// @param dataTimestamp consensus timestamp\n struct Block {\n bytes32 root;\n uint32 dataTimestamp;\n }\n\n /// @param value FCD value\n /// @param dataTimestamp FCD timestamp\n struct FirstClassData {\n uint224 value;\n uint32 dataTimestamp;\n }\n\n /// @param blocksCountOffset number of all blocks that were generated before switching to this contract\n /// @param sequence is a total number of blocks (consensus rounds) including previous contracts\n /// @param lastTimestamp is a timestamp of last submitted block\n /// @param padding number of seconds that need to pass before new submit will be possible\n /// @param deprecated flag that changes to TRUE on `unregister`, when TRUE submissions are not longer available\n struct ConsensusData {\n uint32 blocksCountOffset;\n uint32 sequence;\n uint32 lastTimestamp;\n uint32 padding;\n bool deprecated;\n }\n\n uint256 constant public VERSION = 2;\n\n bool internal immutable _ALLOW_FOR_MIXED_TYPE; // solhint-disable-line var-name-mixedcase\n\n bytes4 constant private _VERSION_SELECTOR = bytes4(keccak256(\"VERSION()\"));\n\n /// @dev minimal number of signatures required for accepting submission (PoA)\n uint16 internal immutable _REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\n\n ConsensusData internal _consensusData;\n\n bytes constant public ETH_PREFIX = \"\\x19Ethereum Signed Message:\\n32\";\n\n /// @dev block id (consensus ID) => root\n /// consensus ID is at the same time consensus timestamp\n mapping(uint256 => bytes32) public roots;\n\n /// @dev FCD key => FCD data\n mapping(bytes32 => FirstClassData) public fcds;\n\n event LogDeprecation(address indexed deprecator);\n event LogPadding(address indexed executor, uint32 timePadding);\n\n error ArraysDataDoNotMatch();\n error AlreadyDeprecated();\n error AlreadyRegistered();\n error BlockSubmittedToFastOrDataToOld();\n error ContractNotReady();\n error FCDOverflow();\n error InvalidContractType();\n error NoChangeToState();\n error OnlyOwnerOrRegistry();\n error UnregisterFirst();\n\n modifier onlyOwnerOrRegistry () {\n if (msg.sender != address(contractRegistry) && msg.sender != owner()) revert OnlyOwnerOrRegistry();\n _;\n }\n\n /// @param _contractRegistry Registry address\n /// @param _padding required \"space\" between blocks in seconds\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n constructor(\n IRegistry _contractRegistry,\n uint32 _padding,\n uint16 _requiredSignatures,\n bool _allowForMixedType\n ) Registrable(_contractRegistry) {\n _ALLOW_FOR_MIXED_TYPE = _allowForMixedType;\n _REQUIRED_SIGNATURES = _requiredSignatures;\n\n _setPadding(_padding);\n\n BaseChain oldChain = BaseChain(_contractRegistry.getAddress(\"Chain\"));\n\n if (address(oldChain) == address(0)) {\n // if this is first contract in sidechain, then we need to initialise lastTimestamp so submission\n // can be possible\n _consensusData.lastTimestamp = uint32(block.timestamp) - _padding - 1;\n }\n }\n\n /// @dev setter for `padding`\n function setPadding(uint16 _padding) external {\n _setPadding(_padding);\n }\n\n /// @notice if this method needs to be called manually (not from Registry)\n /// it is important to do it as part of tx batch\n /// eg using multisig, we should prepare set of transactions and confirm them all at once\n /// @inheritdoc Registrable\n function register() external override onlyOwnerOrRegistry {\n address oldChain = contractRegistry.getAddress(\"Chain\");\n\n // registration must be done before address in registry is replaced\n if (oldChain == address(this)) revert AlreadyRegistered();\n\n if (oldChain == address(0x0)) {\n return;\n }\n\n _cloneLastDataFromPrevChain(oldChain);\n }\n\n /// @inheritdoc Registrable\n function unregister() external override onlyOwnerOrRegistry {\n // in case we deprecated contract manually, we simply return\n if (_consensusData.deprecated) return;\n\n address newChain = contractRegistry.getAddress(\"Chain\");\n // unregistering must be done after address in registry is replaced\n if (newChain == address(this)) revert UnregisterFirst();\n\n // TODO:\n // I think we need to remove restriction for type (at least once)\n // when we will switch to multichain architecture\n\n if (!_ALLOW_FOR_MIXED_TYPE) {\n // can not be replaced with chain of different type\n if (BaseChain(newChain).isForeign() != this.isForeign()) revert InvalidContractType();\n }\n\n _consensusData.deprecated = true;\n emit LogDeprecation(msg.sender);\n }\n\n /// @notice it allows to deprecate contract manually\n /// Only new Registry calls `unregister()` where we set deprecated to true\n /// In old Registries we don't have this feature, so in order to safely redeploy new Chain\n /// we will have to first deprecate current contract manually, then register new contract\n function deprecate() external onlyOwnerOrRegistry {\n if (_consensusData.deprecated) revert AlreadyDeprecated();\n\n _consensusData.deprecated = true;\n emit LogDeprecation(msg.sender);\n }\n\n /// @dev getter for `_consensusData`\n function getConsensusData() external view returns (ConsensusData memory) {\n return _consensusData;\n }\n\n /// @dev number of blocks (consensus rounds) saved in this contract\n function blocksCount() external view returns (uint256) {\n return _consensusData.sequence - _consensusData.blocksCountOffset;\n }\n\n function blocksCountOffset() external view returns (uint32) {\n return _consensusData.blocksCountOffset;\n }\n\n function lastBlockId() external view returns (uint256) {\n return _consensusData.lastTimestamp;\n }\n\n /// @return TRUE if contract is ForeignChain, FALSE otherwise\n function isForeign() external pure virtual returns (bool);\n\n /// @inheritdoc Registrable\n function getName() external pure override returns (bytes32) {\n return \"Chain\";\n }\n\n /// @param _affidavit root and FCDs hashed together\n /// @param _v part of signature\n /// @param _r part of signature\n /// @param _s part of signature\n /// @return signer address\n function recoverSigner(bytes32 _affidavit, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _affidavit));\n return ecrecover(hash, _v, _r, _s);\n }\n\n /// @param _blockId ID of submitted block\n /// @return block data (root + timestamp)\n function blocks(uint256 _blockId) external view returns (Block memory) {\n return Block(roots[_blockId], uint32(_blockId));\n }\n\n /// @return current block ID\n /// please note, that current ID is not the same as last ID, current means that once padding pass,\n /// ID will switch to next one and it will be pointing to empty submit until submit for that ID is done\n function getBlockId() external view returns (uint32) {\n if (_consensusData.lastTimestamp == 0) return 0;\n\n return getBlockIdAtTimestamp(block.timestamp);\n }\n\n function requiredSignatures() external view returns (uint16) {\n return _REQUIRED_SIGNATURES;\n }\n\n /// @dev calculates block ID for provided timestamp\n /// this function does not works for past timestamps\n /// @param _timestamp current or future timestamp\n /// @return block ID for provided timestamp\n function getBlockIdAtTimestamp(uint256 _timestamp) virtual public view returns (uint32) {\n ConsensusData memory data = _consensusData;\n\n unchecked {\n // we can't overflow because we adding two `uint32`\n if (data.lastTimestamp + data.padding < _timestamp) {\n return uint32(_timestamp);\n }\n }\n\n return data.lastTimestamp;\n }\n\n /// @return last submitted block ID, please note, that on deployment, when there is no submission for this contract\n /// block for last ID will be available in previous contract\n function getLatestBlockId() virtual public view returns (uint32) {\n return _consensusData.lastTimestamp;\n }\n\n /// @dev verifies if the leaf is valid leaf for merkle tree\n /// @param _proof merkle proof for merkle tree\n /// @param _root merkle root\n /// @param _leaf leaf hash\n /// @return TRUE if `_leaf` is valid, FALSE otherwise\n function verifyProof(bytes32[] memory _proof, bytes32 _root, bytes32 _leaf) public pure returns (bool) {\n if (_root == bytes32(0)) {\n return false;\n }\n\n return _proof.verify(_root, _leaf);\n }\n\n /// @dev creates leaf hash, that has is used in merkle tree\n /// @param _key key under which we store the value\n /// @param _value value itself as bytes\n /// @return leaf hash\n function hashLeaf(bytes memory _key, bytes memory _value) public pure returns (bytes32) {\n return keccak256(abi.encodePacked(_key, _value));\n }\n\n /// @dev verifies, if provided key-value pair was part of consensus\n /// @param _blockId consensus ID for which we doing a check\n /// @param _proof merkle proof for pair\n /// @param _key pair key\n /// @param _value pair value\n /// @return TRUE if key-value par was part of consensus, FALSE otherwise\n function verifyProofForBlock(\n uint256 _blockId,\n bytes32[] memory _proof,\n bytes memory _key,\n bytes memory _value\n )\n public\n view\n returns (bool)\n {\n return _proof.verify(roots[_blockId], keccak256(abi.encodePacked(_key, _value)));\n }\n\n /// @dev this is helper method, that extracts one merkle proof from many hashed provided as bytes\n /// @param _data many hashes as bytes\n /// @param _offset this is starting point for extraction\n /// @param _items how many hashes to extract\n /// @return merkle proof (array of bytes32 hashes)\n function bytesToBytes32Array(\n bytes memory _data,\n uint256 _offset,\n uint256 _items\n )\n public\n pure\n returns (bytes32[] memory)\n {\n bytes32[] memory dataList = new bytes32[](_items);\n\n // we can unchecked because we working only with `i` and `_offset`\n // in case of wrong `_offset` it will throw\n unchecked {\n for (uint256 i = 0; i < _items; i++) {\n bytes32 temp;\n uint256 idx = (i + 1 + _offset) * 32;\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n temp := mload(add(_data, idx))\n }\n\n dataList[i] = temp;\n }\n }\n\n return (dataList);\n }\n\n /// @dev batch method for data verification\n /// @param _blockIds consensus IDs for which we doing a checks\n /// @param _proofs merkle proofs for all pair, sequence of hashes provided as bytes\n /// @param _proofItemsCounter array of counters, each counter tells how many hashes proof for each leaf has\n /// @param _leaves array of merkle leaves\n /// @return results array of verification results, TRUE if leaf is part of consensus, FALSE otherwise\n function verifyProofs(\n uint32[] memory _blockIds,\n bytes memory _proofs,\n uint256[] memory _proofItemsCounter,\n bytes32[] memory _leaves\n )\n public\n view\n returns (bool[] memory results)\n {\n results = new bool[](_leaves.length);\n uint256 offset = 0;\n\n for (uint256 i = 0; i < _leaves.length;) {\n results[i] = bytesToBytes32Array(_proofs, offset, _proofItemsCounter[i]).verify(\n roots[_blockIds[i]], _leaves[i]\n );\n\n unchecked {\n // we can uncheck because it will not overflow in a lifetime, and if someone provide invalid counter\n // we verification will not be valid (or we throw because of invalid memory access)\n offset += _proofItemsCounter[i];\n // we can uncheck because `i` will not overflow in a lifetime\n i++;\n }\n }\n }\n\n /// @param _blockId consensus ID\n /// @return root for provided consensus ID\n function getBlockRoot(uint32 _blockId) external view returns (bytes32) {\n return roots[_blockId];\n }\n\n /// @param _blockId consensus ID\n /// @return timestamp for provided consensus ID\n function getBlockTimestamp(uint32 _blockId) external view returns (uint32) {\n return roots[_blockId] == bytes32(0) ? 0 : _blockId;\n }\n\n /// @dev batch getter for FCDs\n /// @param _keys FCDs keys to fetch\n /// @return values array of FCDs values\n /// @return timestamps array of FCDs timestamps\n function getCurrentValues(bytes32[] calldata _keys)\n external\n view\n returns (uint256[] memory values, uint32[] memory timestamps)\n {\n timestamps = new uint32[](_keys.length);\n values = new uint256[](_keys.length);\n\n for (uint i=0; i<_keys.length;) {\n FirstClassData storage numericFCD = fcds[_keys[i]];\n values[i] = uint256(numericFCD.value);\n timestamps[i] = numericFCD.dataTimestamp;\n\n unchecked {\n // we can uncheck because `i` will not overflow in a lifetime\n i++;\n }\n }\n }\n\n /// @dev getter for single FCD value\n /// @param _key FCD key\n /// @return value FCD value\n /// @return timestamp FCD timestamp\n function getCurrentValue(bytes32 _key) external view returns (uint256 value, uint256 timestamp) {\n FirstClassData storage numericFCD = fcds[_key];\n return (uint256(numericFCD.value), numericFCD.dataTimestamp);\n }\n\n /// @dev getter for single FCD value in case its type is `int`\n /// @param _key FCD key\n /// @return value FCD value\n /// @return timestamp FCD timestamp\n function getCurrentIntValue(bytes32 _key) external view returns (int256 value, uint256 timestamp) {\n FirstClassData storage numericFCD = fcds[_key];\n return (numericFCD.value.toInt(), numericFCD.dataTimestamp);\n }\n\n function _setPadding(uint32 _padding) internal onlyOwner {\n if (_consensusData.padding == _padding) revert NoChangeToState();\n\n _consensusData.padding = _padding;\n emit LogPadding(msg.sender, _padding);\n }\n\n /// @dev we cloning last block time, because we will need reference point for next submissions\n function _cloneLastDataFromPrevChain(address _prevChain) internal {\n (bool success, bytes memory v) = _prevChain.staticcall(abi.encode(_VERSION_SELECTOR));\n uint256 prevVersion = success ? abi.decode(v, (uint256)) : 1;\n\n if (prevVersion == 1) {\n uint32 latestId = IBaseChainV1(address(_prevChain)).getLatestBlockId();\n _consensusData.lastTimestamp = IBaseChainV1(address(_prevChain)).getBlockTimestamp(latestId);\n\n // +1 because getLatestBlockId subtracts 1\n // +1 because it might be situation when tx is already in progress in old contract\n // and old contract do not have deprecated flag\n _consensusData.sequence = latestId + 2;\n _consensusData.blocksCountOffset = latestId + 2;\n } else { // VERSION 2\n // with new Registry, we have register/unregister methods\n // Chain will be deprecated, so there is no need to do \"+1\" as in old version\n // TODO what with current Registries??\n // we need a way to make it deprecated!\n ConsensusData memory data = BaseChain(_prevChain).getConsensusData();\n\n _consensusData.sequence = data.sequence;\n _consensusData.blocksCountOffset = data.sequence;\n _consensusData.lastTimestamp = data.lastTimestamp;\n }\n }\n}\n" + }, + "contracts/Chain.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./BaseChain.sol\";\n\ncontract Chain is BaseChain {\n IStakingBank public immutable stakingBank;\n\n event LogMint(address indexed minter, uint256 blockId, uint256 staked, uint256 power);\n event LogVoter(uint256 indexed blockId, address indexed voter, uint256 vote);\n\n error NotEnoughSignatures();\n error SignaturesOutOfOrder();\n\n /// @param _contractRegistry Registry address\n /// @param _padding required \"space\" between blocks in seconds\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n /// @param _allowForMixedType we have two \"types\" of Chain: HomeChain and ForeignChain, when we redeploying\n /// we don't want to mix up them, so we checking, if new Chain has the same type as current one.\n /// However, when we will be switching from one homechain to another one, we have to allow for this mixing up.\n /// This flag will tell contract, if this is the case.\n constructor(\n IRegistry _contractRegistry,\n uint32 _padding,\n uint16 _requiredSignatures,\n bool _allowForMixedType\n ) BaseChain(_contractRegistry, _padding, _requiredSignatures, _allowForMixedType) {\n stakingBank = IStakingBank(_contractRegistry.requireAndGetAddress(\"StakingBank\"));\n }\n\n /// @dev method for submitting consensus data\n /// @param _dataTimestamp consensus timestamp, this is time for all data in merkle tree including FCDs\n /// @param _root merkle root\n /// @param _keys FCDs keys\n /// @param _values FCDs values\n /// @param _v array of `v` part of validators signatures\n /// @param _r array of `r` part of validators signatures\n /// @param _s array of `s` part of validators signatures\n // solhint-disable-next-line function-max-lines, code-complexity\n function submit(\n uint32 _dataTimestamp,\n bytes32 _root,\n bytes32[] memory _keys,\n uint256[] memory _values,\n uint8[] memory _v,\n bytes32[] memory _r,\n bytes32[] memory _s\n ) external {\n // below two checks are only for pretty errors, so we can safe gas and allow for raw revert\n // if (_keys.length != _values.length) revert ArraysDataDoNotMatch();\n // if (_v.length != _r.length || _r.length != _s.length) revert ArraysDataDoNotMatch();\n\n _verifySubmitTimestampAndIncSequence(_dataTimestamp);\n\n // we can't expect minter will have exactly the same timestamp\n // but for sure we can demand not to be off by a lot, that's why +3sec\n // temporary remove this condition, because recently on ropsten we see cases when minter/node\n // can be even 100sec behind\n // require(_dataTimestamp <= block.timestamp + 3,\n // string(abi.encodePacked(\"oh, so you can predict the future:\", _dataTimestamp - block.timestamp + 48)));\n\n bytes memory testimony = abi.encodePacked(_dataTimestamp, _root);\n\n for (uint256 i = 0; i < _keys.length;) {\n if (uint224(_values[i]) != _values[i]) revert FCDOverflow();\n\n fcds[_keys[i]] = FirstClassData(uint224(_values[i]), _dataTimestamp);\n testimony = abi.encodePacked(testimony, _keys[i], _values[i]);\n\n unchecked {\n // we can't pass enough data to overflow\n i++;\n }\n }\n\n uint256 signatures = 0;\n uint256 power = 0;\n //uint256 staked = stakingBank.totalSupply();\n bytes32 affidavit = keccak256(testimony);\n\n address prevSigner = address(0x0);\n\n for (uint256 i; i < _v.length;) {\n address signer = recoverSigner(affidavit, _v[i], _r[i], _s[i]);\n uint256 balance = stakingBank.balanceOf(signer);\n\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\n\n prevSigner = signer;\n\n if (balance == 0) {\n unchecked { i++; }\n continue;\n }\n\n signatures++;\n emit LogVoter(uint256(_dataTimestamp), signer, balance);\n\n unchecked {\n // we can't overflow because that means token overflowed\n // and even if we do, we will get lower power\n power += balance;\n i++;\n }\n }\n\n if (signatures < _REQUIRED_SIGNATURES) revert NotEnoughSignatures();\n\n emit LogMint(msg.sender, _dataTimestamp, stakingBank.totalSupply(), power);\n\n // TODO remember to protect against flash loans when DPoS will be in place\n // we turn on power once we have DPoS in action, we have PoA now\n // require(power * 100 / staked >= 66, \"not enough power was gathered\");\n\n roots[_dataTimestamp] = _root;\n _consensusData.lastTimestamp = _dataTimestamp;\n }\n\n /// @inheritdoc BaseChain\n function isForeign() external pure virtual override returns (bool) {\n return false;\n }\n\n /// @dev helper method that returns all important data about current state of contract\n /// @return blockNumber `block.number`\n /// @return timePadding `this.padding`\n /// @return lastDataTimestamp timestamp for last submitted consensus\n /// @return lastId ID of last submitted consensus\n /// @return nextLeader leader for `block.timestamp + 1`\n /// @return nextBlockId block ID for `block.timestamp + padding`\n /// @return validators array of all validators addresses\n /// @return powers array of all validators powers\n /// @return locations array of all validators locations\n /// @return staked total UMB staked by validators\n /// @return minSignatures `this.requiredSignatures`\n function getStatus() external view virtual returns(\n uint256 blockNumber,\n uint32 timePadding,\n uint32 lastDataTimestamp,\n uint32 lastId,\n address nextLeader,\n uint32 nextBlockId,\n address[] memory validators,\n uint256[] memory powers,\n string[] memory locations,\n uint256 staked,\n uint16 minSignatures\n ) {\n ConsensusData memory data = _consensusData;\n\n blockNumber = block.number;\n timePadding = data.padding;\n lastId = data.lastTimestamp;\n lastDataTimestamp = lastId;\n minSignatures = _REQUIRED_SIGNATURES;\n\n staked = stakingBank.totalSupply();\n uint256 numberOfValidators = stakingBank.getNumberOfValidators();\n powers = new uint256[](numberOfValidators);\n validators = new address[](numberOfValidators);\n locations = new string[](numberOfValidators);\n\n for (uint256 i = 0; i < numberOfValidators;) {\n validators[i] = stakingBank.addresses(i);\n (, locations[i]) = stakingBank.validators(validators[i]);\n powers[i] = stakingBank.balanceOf(validators[i]);\n\n unchecked {\n // we will run out of gas before overflow happen\n i++;\n }\n }\n\n unchecked {\n // we will not overflow with timestamp in a lifetime\n nextBlockId = lastId + data.padding + 1;\n\n nextLeader = numberOfValidators > 0\n // we will not overflow with timestamp in a lifetime\n ? validators[getLeaderIndex(numberOfValidators, block.timestamp + 1)]\n : address(0);\n }\n }\n\n /// @return address of leader for next second\n function getNextLeaderAddress() external view returns (address) {\n return getLeaderAddressAtTime(block.timestamp + 1);\n }\n\n /// @return address of current leader\n function getLeaderAddress() external view returns (address) {\n return getLeaderAddressAtTime(block.timestamp);\n }\n\n /// @param _numberOfValidators total number of validators\n /// @param _timestamp timestamp for which you want to calculate index\n /// @return leader index, use it for StakingBank.addresses[index] to fetch leader address\n function getLeaderIndex(uint256 _numberOfValidators, uint256 _timestamp) public view virtual returns (uint256) {\n ConsensusData memory data = _consensusData;\n\n unchecked {\n // we will not overflow on `timestamp` and `padding` in a life time\n // timePadding + 1 => because padding is a space between blocks,\n // so next round starts on first block after padding\n // TODO will it work for off-chain??\n uint256 validatorIndex = data.sequence + (_timestamp - data.lastTimestamp) / (data.padding + 1);\n\n return validatorIndex % _numberOfValidators;\n }\n }\n\n // @todo - properly handled non-enabled validators, newly added validators, and validators with low stake\n /// @param _timestamp timestamp for which you want to calculate leader address\n /// @return leader address for provider timestamp\n function getLeaderAddressAtTime(uint256 _timestamp) public view virtual returns (address) {\n uint256 numberOfValidators = stakingBank.getNumberOfValidators();\n\n if (numberOfValidators == 0) {\n return address(0x0);\n }\n\n uint256 validatorIndex = getLeaderIndex(numberOfValidators, _timestamp);\n\n return stakingBank.addresses(validatorIndex);\n }\n\n /// @dev we had stack too deep in `submit` so this method was created as a solution\n // we increasing `_consensusData.sequence` here so we don't have to read sequence again in other place\n function _verifySubmitTimestampAndIncSequence(uint256 _dataTimestamp) internal {\n ConsensusData memory data = _consensusData;\n\n // `data.lastTimestamp` must be setup either on deployment\n // or via cloning from previous contract\n if (data.lastTimestamp == 0) revert ContractNotReady();\n\n unchecked {\n // we will not overflow with timestamp and padding in a life time\n if (data.lastTimestamp + data.padding >= _dataTimestamp) revert BlockSubmittedToFastOrDataToOld();\n }\n\n unchecked {\n // we will not overflow in a life time\n _consensusData.sequence = uint32(data.sequence + 1);\n }\n }\n}\n" + }, + "contracts/extensions/Registrable.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\n/// @dev Any contract that we want to register in ContractRegistry, must inherit from Registrable\nabstract contract Registrable {\n IRegistry public immutable contractRegistry;\n\n modifier onlyFromContract(address _msgSender, bytes32 _contractName) {\n require(\n contractRegistry.getAddress(_contractName) == _msgSender,\n string(abi.encodePacked(\"caller is not \", _contractName))\n );\n _;\n }\n\n modifier withRegistrySetUp() {\n require(address(contractRegistry) != address(0x0), \"_registry is empty\");\n _;\n }\n\n constructor(IRegistry _contractRegistry) {\n require(address(_contractRegistry) != address(0x0), \"_registry is empty\");\n contractRegistry = _contractRegistry;\n }\n\n /// @dev this method will be called as a first method in registration process when old contract will be replaced\n /// when called, old contract address is still in registry\n function register() virtual external;\n\n /// @dev this method will be called as a last method in registration process when old contract will be replaced\n /// when called, new contract address is already in registry\n function unregister() virtual external;\n\n /// @return contract name as bytes32\n function getName() virtual external pure returns (bytes32);\n\n /// @dev helper method for fetching StakingBank address\n function stakingBankContract() public view returns (IStakingBank) {\n return IStakingBank(contractRegistry.requireAndGetAddress(\"StakingBank\"));\n }\n\n /// @dev helper method for fetching UMB address\n function tokenContract() public view withRegistrySetUp returns (ERC20) {\n return ERC20(contractRegistry.requireAndGetAddress(\"UMB\"));\n }\n}\n" + }, + "contracts/ForeignChain.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./Chain.sol\";\n\n/// @dev contract for foreign chains\ncontract ForeignChain is Chain {\n error NotSupported();\n\n /// @param _contractRegistry Registry address\n /// @param _padding required \"space\" between blocks in seconds\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n constructor(\n IRegistry _contractRegistry,\n uint32 _padding,\n uint16 _requiredSignatures,\n bool _allowForMixedType\n ) Chain(_contractRegistry, _padding, _requiredSignatures, _allowForMixedType) {\n // no additional configuration needed\n }\n\n /// @inheritdoc BaseChain\n function isForeign() external pure override returns (bool) {\n return true;\n }\n\n /// @inheritdoc Chain\n /// @notice this method is made to be compatible with MasterChain, but it does not return full data eg validators\n /// data will be missing.\n /// @return blockNumber `block.number`\n /// @return timePadding `this.padding`\n /// @return lastDataTimestamp timestamp for last submitted consensus\n /// @return lastId ID of last submitted consensus\n /// @return nextLeader will be always address(0)\n /// @return nextBlockId block ID for `block.timestamp + padding`\n /// @return validators array will be always empty\n /// @return powers array will be always empty\n /// @return locations array will be always empty\n /// @return staked total UMB staked by validators\n /// @return minSignatures `this.requiredSignatures`\n function getStatus() external view override returns(\n uint256 blockNumber,\n uint32 timePadding,\n uint32 lastDataTimestamp,\n uint32 lastId,\n address nextLeader,\n uint32 nextBlockId,\n address[] memory validators,\n uint256[] memory powers,\n string[] memory locations,\n uint256 staked,\n uint16 minSignatures\n ) {\n ConsensusData memory data = _consensusData;\n\n blockNumber = block.number;\n timePadding = data.padding;\n lastId = data.lastTimestamp;\n lastDataTimestamp = lastId;\n minSignatures = _REQUIRED_SIGNATURES;\n\n staked = stakingBank.totalSupply();\n uint256 numberOfValidators = 0;\n powers = new uint256[](numberOfValidators);\n validators = new address[](numberOfValidators);\n locations = new string[](numberOfValidators);\n nextLeader = address(0);\n\n unchecked {\n // we will not overflow with timestamp in a lifetime\n nextBlockId = lastId + data.padding + 1;\n }\n }\n\n function getLeaderIndex(uint256, uint256) public pure override returns (uint256) {\n revert NotSupported();\n }\n\n function getLeaderAddressAtTime(uint256) public pure override returns (address) {\n revert NotSupported();\n }\n}\n" + }, + "contracts/interfaces/IBaseChainV1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IBaseChainV1 {\n /// @dev number of blocks (consensus rounds) saved in this contract\n function blocksCount() external returns (uint32);\n\n /// @dev number of all blocks that were generated before switching to this contract\n /// please note, that there might be a gap of one block when we switching from old to new contract\n /// see constructor for details\n function blocksCountOffset() external returns (uint32);\n\n function getLatestBlockId() external view returns (uint32);\n\n function getBlockTimestamp(uint32 _blockId) external view returns (uint32);\n\n function getStatus() external view returns (\n uint256 blockNumber,\n uint16 timePadding,\n uint32 lastDataTimestamp,\n uint32 lastId,\n uint32 nextBlockId\n );\n}\n" + }, + "contracts/interfaces/IRegistry.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\n\ninterface IRegistry {\n event LogRegistered(address indexed destination, bytes32 name);\n\n /// @dev imports new contract addresses and override old addresses, if they exist under provided name\n /// This method can be used for contracts that for some reason do not have `getName` method\n /// @param _names array of contract names that we want to register\n /// @param _destinations array of contract addresses\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external;\n\n /// @dev imports new contracts and override old addresses, if they exist.\n /// Names of contracts are fetched directly from each contract by calling `getName`\n /// @param _destinations array of contract addresses\n function importContracts(address[] calldata _destinations) external;\n\n /// @dev this method ensure, that old and new contract is aware of it state in registry\n /// Note: BSC registry does not have this method. This method was introduced in later stage.\n /// @param _newContract address of contract that will replace old one\n function atomicUpdate(address _newContract) external;\n\n /// @dev similar to `getAddress` but throws when contract name not exists\n /// @param name contract name\n /// @return contract address registered under provided name or throws, if does not exists\n function requireAndGetAddress(bytes32 name) external view returns (address);\n\n /// @param name contract name in a form of bytes32\n /// @return contract address registered under provided name\n function getAddress(bytes32 name) external view returns (address);\n\n /// @param _name contract name\n /// @return contract address assigned to the name or address(0) if not exists\n function getAddressByString(string memory _name) external view returns (address);\n\n /// @dev helper method that converts string to bytes32,\n /// you can use to to generate contract name\n function stringToBytes32(string memory _string) external pure returns (bytes32 result);\n}\n" + }, + "contracts/interfaces/IStakingBank.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IStakingBank is IERC20 {\n /// @param id address of validator wallet\n /// @param location URL of the validator API\n struct Validator {\n address id;\n string location;\n }\n\n event LogValidatorRegistered(address indexed id);\n event LogValidatorUpdated(address indexed id);\n event LogValidatorRemoved(address indexed id);\n event LogMinAmountForStake(uint256 minAmountForStake);\n\n /// @dev setter for `minAmountForStake`\n function setMinAmountForStake(uint256 _minAmountForStake) external;\n\n /// @dev allows to stake `token` by validators\n /// Validator needs to approve StakingBank beforehand\n /// @param _value amount of tokens to stake\n function stake(uint256 _value) external;\n\n /// @dev notification about approval from `_from` address on UMB token\n /// Staking bank will stake max approved amount from `_from` address\n /// @param _from address which approved token spend for IStakingBank\n function receiveApproval(address _from) external returns (bool success);\n\n /// @dev withdraws stake tokens\n /// it throws, when balance will be less than required minimum for stake\n /// to withdraw all use `exit`\n function withdraw(uint256 _value) external returns (bool success);\n\n /// @dev unstake and withdraw all tokens\n function exit() external returns (bool success);\n\n /// @dev creates (register) new validator\n /// @param _id validator address\n /// @param _location location URL of the validator API\n function create(address _id, string calldata _location) external;\n\n /// @dev removes validator\n /// @param _id validator wallet\n function remove(address _id) external;\n\n /// @dev updates validator location\n /// @param _id validator wallet\n /// @param _location new validator URL\n function update(address _id, string calldata _location) external;\n\n /// @return total number of registered validators (with and without balance)\n function getNumberOfValidators() external view returns (uint256);\n\n /// @dev gets validator address for provided index\n /// @param _ix index in array of list of all validators wallets\n function addresses(uint256 _ix) external view returns (address);\n\n /// @param _id address of validator\n /// @return id address of validator\n /// @return location URL of validator\n function validators(address _id) external view returns (address id, string memory location);\n}\n" + }, + "contracts/interfaces/IStakingBankStatic.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./IStakingBank.sol\";\n\n\ninterface IStakingBankStatic is IStakingBank {\n /// @param _validators array of validators addresses to verify\n /// @return TRUE when all validators are valid, FALSE otherwise\n function verifyValidators(address[] calldata _validators) external view returns (bool);\n}\n" + }, + "contracts/interfaces/IUmbrellaFeeds.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IUmbrellaFeeds {\n struct PriceData {\n /// @dev this is placeholder, that can be used for some additional data\n /// atm of creating this smart contract, it is only used as marker for removed data (when == type(uint8).max)\n uint8 data;\n /// @dev heartbeat: how often price data will be refreshed in case price stay flat\n uint24 heartbeat;\n /// @dev timestamp: price time, at this time validators run consensus\n uint32 timestamp;\n /// @dev price\n uint128 price;\n }\n\n struct Signature {\n uint8 v;\n bytes32 r;\n bytes32 s;\n }\n\n /// @dev method for submitting consensus data\n /// @param _priceKeys array of keys for `_priceDatas`\n /// @param _priceDatas PriceData signed by validators\n /// @param _signatures validators signatures\n function update(\n bytes32[] calldata _priceKeys,\n PriceData[] calldata _priceDatas,\n Signature[] calldata _signatures\n ) external;\n\n /// @dev it will return array of price datas for provided `_keys`\n /// In case ony of feed does not exist, fallback call will be executed for that feed.\n /// @notice If data for any key not exists, function will revert. Use `getManyPriceDataRaw` method if you don't\n /// want revert.\n /// @param _keys array of feed keys\n /// @return data PriceData array\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data);\n\n /// @dev same as getManyPriceData() but does not revert on empty data.\n /// @notice This method does no revert if some data does not exists.\n /// Check `data.timestamp` to see if price exist, if it is 0, then it does not exist.\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data);\n\n /// @dev this is main endpoint for reading feeds.\n /// In case timestamp is empty (that means there is no data), contract will revert.\n /// If you do not need whole data from `PriceData` struct, you can save some gas by using other view methods that\n /// returns just what you need.\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return data full PriceData struct\n function getPriceData(bytes32 _key) external view returns (PriceData memory data);\n\n /// @notice reader for mapping\n /// @param _key hash of feed name\n /// @return data full PriceData struct\n function prices(bytes32 _key) external view returns (PriceData memory data);\n\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return price\n function getPrice(bytes32 _key) external view returns (uint128 price);\n\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return price\n /// @return timestamp\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp);\n\n /// @notice method will revert if data for `_key` not exists.\n /// @param _key hash of feed name\n /// @return price\n /// @return timestamp\n /// @return heartbeat\n function getPriceTimestampHeartbeat(bytes32 _key)\n external\n view\n returns (uint128 price, uint32 timestamp, uint24 heartbeat);\n\n /// @dev This method should be used only for Layer2 as it is more gas consuming than others views.\n /// @notice It does not revert on empty data.\n /// @param _name string feed name\n /// @return data PriceData\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data);\n\n /// @dev decimals for prices stored in this contract\n function DECIMALS() external view returns (uint8); // solhint-disable-line func-name-mixedcase\n}\n" + }, + "contracts/interfaces/StakingBankStaticNotSupported.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./IStakingBank.sol\";\n\nabstract contract StakingBankStaticNotSupported is IStakingBank {\n error NotSupported();\n\n function create(address, string calldata) external pure {\n revert NotSupported();\n }\n\n function update(address, string calldata) external pure {\n revert NotSupported();\n }\n\n function remove(address) external pure {\n revert NotSupported();\n }\n\n function transfer(address, uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function transferFrom(address, address, uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function receiveApproval(address) external pure returns (bool) {\n revert NotSupported();\n }\n\n function allowance(address, address) external pure returns (uint256) {\n revert NotSupported();\n }\n\n function approve(address, uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function stake(uint256) external pure {\n revert NotSupported();\n }\n\n function withdraw(uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function exit() external pure returns (bool) {\n revert NotSupported();\n }\n\n function setMinAmountForStake(uint256) external pure {\n revert NotSupported();\n }\n}\n" + }, + "contracts/mock/Distributor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport \"../Registry.sol\";\n\ncontract Distributor is Ownable {\n address[] public recipients;\n uint256 public bottomLimit = 5e17;\n uint256 public topLimit = 1e18;\n\n constructor(address[] memory _recipients) {\n recipients = _recipients;\n }\n\n receive() external payable {\n distribute();\n }\n\n function setLimits(uint256 _bottom, uint256 _top) external onlyOwner {\n bottomLimit = _bottom;\n topLimit = _top;\n }\n\n function withdraw() external {\n uint balance = address(this).balance;\n uint buffer = recipients.length * (topLimit - bottomLimit);\n\n if (balance > buffer) {\n payable(owner()).transfer(balance - buffer);\n }\n }\n\n function addRecipients(address[] calldata _recipients) external onlyOwner {\n for (uint256 i = 0; i < _recipients.length; i++) {\n recipients.push(_recipients[i]);\n }\n }\n\n function removeRecipient(address _recipient) external onlyOwner {\n for (uint256 i = 0; i < recipients.length; i++) {\n if (recipients[i] == _recipient) {\n recipients[i] = recipients[recipients.length - 1];\n recipients.pop();\n return;\n }\n }\n }\n\n function recipientsCount() external view returns (uint256) {\n return recipients.length;\n }\n\n function allRecipients() external view returns (address[] memory) {\n return recipients;\n }\n\n function getName() external pure returns (bytes32) {\n return \"Distributor\";\n }\n\n function distribute() public {\n uint256 limit = bottomLimit;\n uint256 top = topLimit;\n uint256 count = recipients.length;\n uint256 totalBalance = address(this).balance;\n\n for (uint256 i = 0; i < count; i++) {\n uint256 balance = recipients[i].balance;\n\n if (balance > limit) {\n continue;\n }\n\n uint256 amount = top - balance > totalBalance ? totalBalance : top - balance;\n\n if (amount > 0) {\n payable(recipients[i]).transfer(amount);\n totalBalance -= amount;\n }\n }\n }\n}\n" + }, + "contracts/mock/LimitedMintingToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\ncontract LimitedMintingToken is ERC20, Ownable {\n struct MintData {\n uint256 dailyAllowance;\n mapping (address => uint256) lastMintTimestamp;\n mapping (address => uint256) todaysMintedAmount;\n }\n\n MintData public mintData;\n\n constructor(string memory _name, string memory _symbol, uint256 _dailyAllowance) ERC20(_name, _symbol) {\n mintData.dailyAllowance = _dailyAllowance;\n }\n\n function mint(address _holder, uint256 _amount) external {\n MintData storage data = mintData;\n\n (uint256 limit, bool fullLimit) = _currentLimit(data);\n\n require(limit > 0, \"This address already claimed the maximum daily amount\");\n\n uint256 lastTimestamp = data.lastMintTimestamp[msg.sender];\n uint256 mintedAmount = data.todaysMintedAmount[msg.sender];\n\n uint256 amount = _amount > limit ? limit : _amount;\n data.lastMintTimestamp[msg.sender] = fullLimit ? block.timestamp : lastTimestamp;\n data.todaysMintedAmount[msg.sender] = fullLimit ? amount : mintedAmount + amount;\n\n _mint(_holder, amount);\n }\n\n function mintApproveAndStake(IStakingBank _stakingBank, address _holder, uint256 _amount) external {\n _mint(_holder, _amount);\n _approve(_holder, address(_stakingBank), _amount);\n _stakingBank.receiveApproval(_holder);\n }\n\n function getDailyAllowance() external view returns (uint256) {\n return mintData.dailyAllowance;\n }\n\n function getName() external pure returns (bytes32) {\n return \"UMB\";\n }\n\n function setDailyAllowance(uint256 newDailyAllowance) public onlyOwner {\n MintData storage data = mintData;\n data.dailyAllowance = newDailyAllowance;\n }\n\n function _currentLimit(MintData storage data) internal view returns (uint256 limit, bool fullLimit) {\n uint256 lastMint = data.lastMintTimestamp[msg.sender];\n fullLimit = block.timestamp - lastMint >= 24 hours;\n\n uint256 usedLimit = data.todaysMintedAmount[msg.sender];\n\n limit = fullLimit ? data.dailyAllowance : data.dailyAllowance - usedLimit;\n }\n}\n" + }, + "contracts/mock/Token.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\n// please remember this is our dummy token!\n// it will be replaced by proper DPoS solution in future\ncontract Token is ERC20 {\n constructor(\n string memory _name,\n string memory _symbol) ERC20(_name, _symbol) {\n }\n\n function mint(address _holder, uint256 _amount) external {\n _mint(_holder, _amount);\n }\n\n function mintApproveAndStake(IStakingBank _stakingBank, address _holder, uint256 _amount) external {\n _mint(_holder, _amount);\n _approve(_holder, address(_stakingBank), _amount);\n _stakingBank.receiveApproval(_holder);\n }\n\n function getName() external pure returns (bytes32) {\n return \"UMB\";\n }\n}\n" + }, + "contracts/onChainFeeds/UmbrellaFeeds.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/IUmbrellaFeeds.sol\";\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IStakingBankStatic.sol\";\n\n/// @dev Main contract for all on-chain data.\n/// Check `UmbrellaFeedsReader` to see how to integrate.\n///\n/// @notice This contract can be destroyed and replaced with new one (with new address).\n/// For best gas efficiency you should pick one of two ways of integration:\n/// 1. make `UmbrellaFeeds` immutable and use fallback in case of selfdestruct. After new deployment, it is recommended\n/// to update address to avoid fallback and reduce gas cost to minimum. In long run this is most efficient solution,\n/// better than any proxy.\n/// 2. always check newest `UmbrellaFeeds` via `Regostry` and fallback will not be needed.\ncontract UmbrellaFeeds is IUmbrellaFeeds {\n bytes constant public ETH_PREFIX = \"\\x19Ethereum Signed Message:\\n32\";\n string constant public NAME = \"UmbrellaFeeds\";\n\n /// @dev deployment time, used for protect for unintentional destroy\n uint256 public immutable DEPLOYED_AT; // solhint-disable-line var-name-mixedcase\n\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\n /// resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev StakingBank contract where list of validators is stored\n IStakingBankStatic public immutable STAKING_BANK; // solhint-disable-line var-name-mixedcase\n\n /// @dev minimal number of signatures required for accepting price submission (PoA)\n uint16 public immutable REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\n\n /// @dev decimals for prices stored in this contract\n uint8 public immutable DECIMALS; // solhint-disable-line var-name-mixedcase\n\n /// @notice map of all prices stored in this contract, key for map is hash of feed name\n /// eg for \"ETH-USD\" feed, key will be hash(\"ETH-USD\")\n mapping (bytes32 => PriceData) private _prices;\n\n error ArraysDataDoNotMatch();\n error FeedNotExist();\n error NotEnoughSignatures();\n error InvalidSigner();\n error InvalidRequiredSignatures();\n error SignaturesOutOfOrder();\n error ECDSAInvalidSignatureS();\n error ECDSAInvalidSignatureV();\n error OldData();\n error ContractInUse();\n error ContractNotInitialised();\n\n /// @param _contractRegistry Registry address\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n /// @param _decimals decimals for prices stored in this contract\n constructor(\n IRegistry _contractRegistry,\n uint16 _requiredSignatures,\n uint8 _decimals\n ) {\n if (_requiredSignatures == 0) revert InvalidRequiredSignatures();\n\n REGISTRY = _contractRegistry;\n REQUIRED_SIGNATURES = _requiredSignatures;\n STAKING_BANK = IStakingBankStatic(_contractRegistry.requireAndGetAddress(\"StakingBank\"));\n DECIMALS = _decimals;\n DEPLOYED_AT = block.timestamp;\n }\n\n /// @dev destroys old contract\n /// there is sanity check that prevents abuse of destroy method\n /// @param _name string feed key to verify, that contract was initialised\n function destroy(string calldata _name) external {\n if (REGISTRY.getAddressByString(NAME) == address(this)) revert ContractInUse();\n\n if (_prices[keccak256(abi.encodePacked(_name))].timestamp == 0 && DEPLOYED_AT + 3 days > block.timestamp) {\n revert ContractNotInitialised();\n }\n\n selfdestruct(payable(msg.sender));\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function update(\n bytes32[] calldata _priceKeys,\n PriceData[] calldata _priceDatas,\n Signature[] calldata _signatures\n ) external {\n if (_priceKeys.length != _priceDatas.length) revert ArraysDataDoNotMatch();\n\n bytes32 priceDataHash = keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n verifySignatures(priceDataHash, _signatures);\n\n uint256 i;\n\n while (i < _priceDatas.length) {\n bytes32 priceKey = _priceKeys[i];\n\n // we do not allow for older prices\n // at the same time it prevents from reusing signatures\n if (_prices[priceKey].timestamp >= _priceDatas[i].timestamp) revert OldData();\n\n _prices[priceKey] = _priceDatas[i];\n\n // atm there is no need for events, so in order to save gas, we do not emit any\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n if (data[i].timestamp == 0) revert FeedNotExist();\n\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function prices(bytes32 _key) external view returns (PriceData memory data) {\n data = _prices[_key];\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceData(bytes32 _key) external view returns (PriceData memory data) {\n data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPrice(bytes32 _key) external view returns (uint128 price) {\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return data.price;\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp) {\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp);\n }\n\n function getPriceTimestampHeartbeat(bytes32 _key)\n external\n view\n returns (uint128 price, uint32 timestamp, uint24 heartbeat)\n {\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp, data.heartbeat);\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data) {\n bytes32 key = keccak256(abi.encodePacked(_name));\n data = _prices[key];\n }\n\n /// @dev helper method for QA purposes\n /// @return hash of data that are signed by validators (keys and priced data)\n function hashData(bytes32[] calldata _priceKeys, PriceData[] calldata _priceDatas)\n external\n view\n returns (bytes32)\n {\n return keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n }\n\n /// @param _hash hash of signed data\n /// @param _signatures array of validators signatures\n function verifySignatures(bytes32 _hash, Signature[] calldata _signatures) public view {\n address prevSigner = address(0x0);\n\n if (_signatures.length < REQUIRED_SIGNATURES) revert NotEnoughSignatures();\n\n address[] memory validators = new address[](REQUIRED_SIGNATURES);\n\n // to save gas we check only required number of signatures\n // case, where you can have part of signatures invalid but still enough valid in total is not supported\n for (uint256 i; i < REQUIRED_SIGNATURES;) {\n (uint8 v, bytes32 r, bytes32 s) = (_signatures[i].v, _signatures[i].r, _signatures[i].s);\n\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n revert ECDSAInvalidSignatureS();\n }\n\n if (uint8(v) != 27 && uint8(v) != 28) revert ECDSAInvalidSignatureV();\n\n address signer = recoverSigner(_hash, v, r, s);\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\n\n // because we check only required number of signatures, any invalid one will cause revert\n prevSigner = signer;\n validators[i] = signer;\n\n unchecked { i++; }\n }\n\n // bulk verification can optimise gas when we have 5 or more validators\n if (!STAKING_BANK.verifyValidators(validators)) revert InvalidSigner();\n }\n\n function getChainId() public view returns (uint256 id) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n id := chainid()\n }\n }\n\n /// @param _hash hashed of data\n /// @param _v part of signature\n /// @param _r part of signature\n /// @param _s part of signature\n /// @return signer address\n function recoverSigner(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _hash));\n return ecrecover(hash, _v, _r, _s);\n }\n\n /// @dev to follow Registrable interface\n function getName() public pure returns (bytes32) {\n return \"UmbrellaFeeds\";\n }\n}\n" + }, + "contracts/onChainFeeds/UmbrellaFeedsReader.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IUmbrellaFeeds.sol\";\n\n/// @dev This is optional price reader for just one feed.\n/// It comes with chanilink interface that makes migration process easier.\n/// For maximum gas optimisation it is recommended to use UmbrellaFeeds directly - simply follow this contract as\n/// a guide for integration.\n///\n/// This contract has build in fallback feature in case, `UmbrellaFeeds` will be replaced by newer contract.\n/// Fallback is transparent for the user, no additional setup is needed.\n///\n/// How fallback feature works? If data for provided key is empty (when UmbrellaFeeds was destroyed and replaced),\n/// contract will execute following procedure:\n/// 1. if data is empty, contract will check if there is new registered contract with requested data\n/// 2. if data is found in new contract it will be returned\n/// 3. if there is no data or there is no new contract tx will revert.\ncontract UmbrellaFeedsReader {\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\n /// resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev contract where all the feeds are stored\n address public immutable UMBRELLA_FEEDS; // solhint-disable-line var-name-mixedcase\n\n /// @dev key (hash of string key), under which feed is being stored\n bytes32 public immutable KEY; // solhint-disable-line var-name-mixedcase\n\n /// @dev string representation of feed key (feed name)\n string public description;\n\n /// @dev decimals for feed\n uint8 internal immutable _DECIMALS; // solhint-disable-line var-name-mixedcase\n\n error EmptyAddress();\n error FeedNotExist();\n\n /// @param _registry IRegistry address\n /// @param _umbrellaFeeds UmbrellaFeeds address\n /// @param _key price data key (before hashing)\n constructor(IRegistry _registry, IUmbrellaFeeds _umbrellaFeeds, string memory _key) {\n if (address(_registry) == address(0)) revert EmptyAddress();\n\n REGISTRY = _registry;\n UMBRELLA_FEEDS = address(_umbrellaFeeds);\n description = _key;\n _DECIMALS = _umbrellaFeeds.DECIMALS();\n\n bytes32 hash = keccak256(abi.encodePacked(_key));\n KEY = hash;\n\n // sanity check\n _umbrellaFeeds.getPriceData(hash);\n }\n\n /// @dev decimals for feed\n function decimals() external view returns (uint8) {\n return _DECIMALS;\n }\n\n /// @dev this method follows chainlink interface for easy migration, NOTE: not all returned data are covered!\n /// latestRoundData() raise exception when there is no data, instead of returning unset values,\n /// which could be misinterpreted as actual reported values.\n /// It DOES NOT raise when data is outdated (based on heartbeat and timestamp).\n /// @notice You can save some gas by doing call directly to `UMBRELLA_FEEDS` contract.\n /// @return uint80 originally `roundId`, not in use, always 0\n /// @return answer price\n /// @return uint256 originally `startedAt`, not in use, always 0\n /// @return updatedAt last timestamp data was updated\n /// @return uint80 originally `answeredInRound` not in use, always 0\n function latestRoundData()\n external\n view\n returns (\n uint80 /* roundId */,\n int256 answer,\n uint256 /* startedAt */,\n uint256 updatedAt,\n uint80 /* answeredInRound */\n )\n {\n IUmbrellaFeeds.PriceData memory priceData = _getPriceDataRaw();\n\n if (priceData.timestamp == 0) {\n priceData = _fallbackCall();\n }\n\n return (0, int256(uint256(priceData.price)), 0, priceData.timestamp, 0);\n }\n\n /// @dev this is main endpoint for reading feed. Feed is read from UmbrellaFeeds contract using hardcoded `KEY`.\n /// In case timestamp is empty (that means there is no data), contract will execute fallback call.\n /// @notice revert on empty data\n function getPriceData() external view returns (IUmbrellaFeeds.PriceData memory priceData) {\n priceData = _getPriceDataRaw();\n\n if (priceData.timestamp == 0) {\n priceData = _fallbackCall();\n }\n }\n\n /// @dev same as `getPriceData` but does not revert when no data\n function getPriceDataRaw() external view returns (IUmbrellaFeeds.PriceData memory priceData) {\n priceData = _getPriceDataRaw();\n\n if (priceData.timestamp == 0) {\n return _fallbackCallRaw();\n }\n }\n\n /// @dev same as `getPriceData` but does not revert when no data\n function _getPriceDataRaw() internal view returns (IUmbrellaFeeds.PriceData memory priceData) {\n (bool success, bytes memory data) = UMBRELLA_FEEDS.staticcall(\n abi.encodeWithSelector(IUmbrellaFeeds.prices.selector, KEY)\n );\n\n if (success && data.length != 0) {\n priceData = abi.decode(data, (IUmbrellaFeeds.PriceData));\n }\n }\n\n /// @dev it will revert on empty data\n function _fallbackCall() internal view returns (IUmbrellaFeeds.PriceData memory data) {\n address umbrellaFeeds = REGISTRY.getAddressByString(\"UmbrellaFeeds\");\n\n // if contract was NOT updated, fallback is not needed, data does not exist - revert\n if (umbrellaFeeds == UMBRELLA_FEEDS) revert FeedNotExist();\n\n data = IUmbrellaFeeds(umbrellaFeeds).getPriceData(KEY);\n }\n\n /// @dev it will not revert on empty data\n function _fallbackCallRaw() internal view returns (IUmbrellaFeeds.PriceData memory data) {\n address umbrellaFeeds = REGISTRY.getAddressByString(\"UmbrellaFeeds\");\n\n // if contract was updated, we do fallback\n if (umbrellaFeeds != UMBRELLA_FEEDS) {\n data = IUmbrellaFeeds(umbrellaFeeds).prices(KEY);\n }\n }\n}\n" + }, + "contracts/onChainFeeds/UmbrellaFeedsReaderFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/IRegistry.sol\";\nimport \"../interfaces/IStakingBank.sol\";\n\nimport \"./UmbrellaFeedsReader.sol\";\n\n/// @notice Factory to deploy UmbrellaFeedsReader contract\ncontract UmbrellaFeedsReaderFactory {\n /// @dev Registry contract where list of all addresses is stored. Used to resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev list of all readers\n mapping (bytes32 => UmbrellaFeedsReader) public readers;\n\n event NewUmbrellaFeedsReader(UmbrellaFeedsReader indexed umbrellaFeedsReader, string feedName);\n\n error EmptyAddress();\n\n constructor(IRegistry _registry) {\n if (address(_registry) == address(0)) revert EmptyAddress();\n\n REGISTRY = _registry;\n }\n\n /// @dev Method to deploy new UmbrellaFeedsReader for particular key.\n /// This deployment is optional and it can be done by anyone who needs it.\n /// Reader can be used to simplify migration from Chainlink to Umbrella.\n ///\n /// Check UmbrellaFeedsReader docs for more details.\n ///\n /// We not using minimal proxy because it does not allow for immutable variables.\n /// @param _feedName string Feed name that is registered in UmbrellaFeeds\n /// @return reader UmbrellaFeedsReader contract address, in case anyone wants to use it from Layer1\n function deploy(string memory _feedName) external returns (UmbrellaFeedsReader reader) {\n reader = deployed(_feedName);\n IUmbrellaFeeds umbrellaFeeds = IUmbrellaFeeds(REGISTRY.getAddressByString(\"UmbrellaFeeds\"));\n\n // if UmbrellaFeeds contract is up to date, there is no need to redeploy\n if (address(reader) != address(0) && address(reader.UMBRELLA_FEEDS()) == address(umbrellaFeeds)) {\n return reader;\n }\n\n reader = new UmbrellaFeedsReader(REGISTRY, umbrellaFeeds, _feedName);\n readers[hash(_feedName)] = reader;\n\n emit NewUmbrellaFeedsReader(reader, _feedName);\n }\n\n function deployed(string memory _feedName) public view returns (UmbrellaFeedsReader) {\n return readers[hash(_feedName)];\n }\n\n function hash(string memory _feedName) public pure returns (bytes32) {\n return keccak256(abi.encodePacked(_feedName));\n }\n\n /// @dev to follow Registrable interface\n function getName() public pure returns (bytes32) {\n return \"UmbrellaFeedsReaderFactory\";\n }\n}\n" + }, + "contracts/onChainFeeds/zk-link/UmbrellaFeeds.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../../interfaces/IUmbrellaFeeds.sol\";\nimport \"../../interfaces/IRegistry.sol\";\nimport \"../../interfaces/IStakingBankStatic.sol\";\n\n/// @dev Main contract for all on-chain data.\n/// Check `UmbrellaFeedsReader` to see how to integrate.\n///\n/// @notice This contract can be destroyed and replaced with new one (with new address).\n/// For best gas efficiency you should pick one of two ways of integration:\n/// 1. make `UmbrellaFeeds` immutable and use fallback in case of selfdestruct. After new deployment, it is recommended\n/// to update address to avoid fallback and reduce gas cost to minimum. In long run this is most efficient solution,\n/// better than any proxy.\n/// 2. always check newest `UmbrellaFeeds` via `Regostry` and fallback will not be needed.\ncontract UmbrellaFeeds is IUmbrellaFeeds {\n bytes constant public ETH_PREFIX = \"\\x19Ethereum Signed Message:\\n32\";\n string constant public NAME = \"UmbrellaFeeds\";\n\n /// @dev deployment time, used for protect for unintentional destroy\n uint256 public immutable DEPLOYED_AT; // solhint-disable-line var-name-mixedcase\n\n /// @dev Registry contract where list of all addresses is stored. Fallback feature uses this registry to\n /// resolve newest `UmbrellaFeeds` address\n IRegistry public immutable REGISTRY; // solhint-disable-line var-name-mixedcase\n\n /// @dev StakingBank contract where list of validators is stored\n IStakingBankStatic public immutable STAKING_BANK; // solhint-disable-line var-name-mixedcase\n\n /// @dev minimal number of signatures required for accepting price submission (PoA)\n uint16 public immutable REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase\n\n /// @dev decimals for prices stored in this contract\n uint8 public immutable DECIMALS; // solhint-disable-line var-name-mixedcase\n\n /// @dev in case selfdestruct is not supported, this flag will make sure contract is not usable anymore\n bool public disabled;\n\n /// @notice map of all prices stored in this contract, key for map is hash of feed name\n /// eg for \"ETH-USD\" feed, key will be hash(\"ETH-USD\")\n mapping (bytes32 => PriceData) private _prices;\n\n error SelfDestruct();\n error ArraysDataDoNotMatch();\n error FeedNotExist();\n error NotEnoughSignatures();\n error InvalidSigner();\n error InvalidRequiredSignatures();\n error SignaturesOutOfOrder();\n error ECDSAInvalidSignatureS();\n error ECDSAInvalidSignatureV();\n error OldData();\n error ContractInUse();\n error ContractNotInitialised();\n\n /// @param _contractRegistry Registry address\n /// @param _requiredSignatures number of required signatures for accepting consensus submission\n /// @param _decimals decimals for prices stored in this contract\n constructor(\n IRegistry _contractRegistry,\n uint16 _requiredSignatures,\n uint8 _decimals\n ) {\n if (_requiredSignatures == 0) revert InvalidRequiredSignatures();\n\n REGISTRY = _contractRegistry;\n REQUIRED_SIGNATURES = _requiredSignatures;\n STAKING_BANK = IStakingBankStatic(_contractRegistry.requireAndGetAddress(\"StakingBank\"));\n DECIMALS = _decimals;\n DEPLOYED_AT = block.timestamp;\n }\n\n /// @dev destroys old contract\n /// there is sanity check that prevents abuse of destroy method\n /// @param _name string feed key to verify, that contract was initialised\n function destroy(string calldata _name) external {\n if (REGISTRY.getAddressByString(NAME) == address(this)) revert ContractInUse();\n\n if (_prices[keccak256(abi.encodePacked(_name))].timestamp == 0 && DEPLOYED_AT + 3 days > block.timestamp) {\n revert ContractNotInitialised();\n }\n\n disabled = true;\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function update(\n bytes32[] calldata _priceKeys,\n PriceData[] calldata _priceDatas,\n Signature[] calldata _signatures\n ) external {\n if (disabled) revert SelfDestruct();\n if (_priceKeys.length != _priceDatas.length) revert ArraysDataDoNotMatch();\n\n bytes32 priceDataHash = keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n verifySignatures(priceDataHash, _signatures);\n\n uint256 i;\n\n while (i < _priceDatas.length) {\n bytes32 priceKey = _priceKeys[i];\n\n // we do not allow for older prices\n // at the same time it prevents from reusing signatures\n if (_prices[priceKey].timestamp >= _priceDatas[i].timestamp) revert OldData();\n\n _prices[priceKey] = _priceDatas[i];\n\n // atm there is no need for events, so in order to save gas, we do not emit any\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceData(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n if (disabled) revert SelfDestruct();\n\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n if (data[i].timestamp == 0) revert FeedNotExist();\n\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getManyPriceDataRaw(bytes32[] calldata _keys) external view returns (PriceData[] memory data) {\n if (disabled) revert SelfDestruct();\n\n data = new PriceData[](_keys.length);\n\n for (uint256 i; i < _keys.length;) {\n data[i] = _prices[_keys[i]];\n unchecked { i++; }\n }\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function prices(bytes32 _key) external view returns (PriceData memory data) {\n if (disabled) revert SelfDestruct();\n\n data = _prices[_key];\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceData(bytes32 _key) external view returns (PriceData memory data) {\n if (disabled) revert SelfDestruct();\n\n data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPrice(bytes32 _key) external view returns (uint128 price) {\n if (disabled) revert SelfDestruct();\n\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return data.price;\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceTimestamp(bytes32 _key) external view returns (uint128 price, uint32 timestamp) {\n if (disabled) revert SelfDestruct();\n\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp);\n }\n\n function getPriceTimestampHeartbeat(bytes32 _key)\n external\n view\n returns (uint128 price, uint32 timestamp, uint24 heartbeat)\n {\n if (disabled) revert SelfDestruct();\n\n PriceData memory data = _prices[_key];\n if (data.timestamp == 0) revert FeedNotExist();\n\n return (data.price, data.timestamp, data.heartbeat);\n }\n\n /// @inheritdoc IUmbrellaFeeds\n function getPriceDataByName(string calldata _name) external view returns (PriceData memory data) {\n if (disabled) revert SelfDestruct();\n\n bytes32 key = keccak256(abi.encodePacked(_name));\n data = _prices[key];\n }\n\n /// @dev helper method for QA purposes\n /// @return hash of data that are signed by validators (keys and priced data)\n function hashData(bytes32[] calldata _priceKeys, PriceData[] calldata _priceDatas)\n external\n view\n returns (bytes32)\n {\n return keccak256(abi.encode(getChainId(), address(this), _priceKeys, _priceDatas));\n }\n\n /// @param _hash hash of signed data\n /// @param _signatures array of validators signatures\n function verifySignatures(bytes32 _hash, Signature[] calldata _signatures) public view {\n address prevSigner = address(0x0);\n\n if (_signatures.length < REQUIRED_SIGNATURES) revert NotEnoughSignatures();\n\n address[] memory validators = new address[](REQUIRED_SIGNATURES);\n\n // to save gas we check only required number of signatures\n // case, where you can have part of signatures invalid but still enough valid in total is not supported\n for (uint256 i; i < REQUIRED_SIGNATURES;) {\n (uint8 v, bytes32 r, bytes32 s) = (_signatures[i].v, _signatures[i].r, _signatures[i].s);\n\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n revert ECDSAInvalidSignatureS();\n }\n\n if (uint8(v) != 27 && uint8(v) != 28) revert ECDSAInvalidSignatureV();\n\n address signer = recoverSigner(_hash, v, r, s);\n if (prevSigner >= signer) revert SignaturesOutOfOrder();\n\n // because we check only required number of signatures, any invalid one will cause revert\n prevSigner = signer;\n validators[i] = signer;\n\n unchecked { i++; }\n }\n\n // bulk verification can optimise gas when we have 5 or more validators\n if (!STAKING_BANK.verifyValidators(validators)) revert InvalidSigner();\n }\n\n function getChainId() public view returns (uint256 id) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n id := chainid()\n }\n }\n\n /// @param _hash hashed of data\n /// @param _v part of signature\n /// @param _r part of signature\n /// @param _s part of signature\n /// @return signer address\n function recoverSigner(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {\n bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _hash));\n return ecrecover(hash, _v, _r, _s);\n }\n\n /// @dev to follow Registrable interface\n function getName() public pure returns (bytes32) {\n return \"UmbrellaFeeds\";\n }\n}\n" + }, + "contracts/Registry.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\n// Inheritance\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport \"./extensions/Registrable.sol\";\nimport \"./interfaces/IRegistry.sol\";\n\n/// @dev contracts registry\n/// protocol uses this registry to fetch current contract addresses\ncontract Registry is IRegistry, Ownable {\n /// name => contract address\n mapping(bytes32 => address) public registry;\n\n\n error NameNotRegistered();\n error ArraysDataDoNotMatch();\n\n /// @inheritdoc IRegistry\n function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external onlyOwner {\n if (_names.length != _destinations.length) revert ArraysDataDoNotMatch();\n\n for (uint i = 0; i < _names.length;) {\n registry[_names[i]] = _destinations[i];\n emit LogRegistered(_destinations[i], _names[i]);\n\n unchecked {\n i++;\n }\n }\n }\n\n /// @inheritdoc IRegistry\n function importContracts(address[] calldata _destinations) external onlyOwner {\n for (uint i = 0; i < _destinations.length;) {\n bytes32 name = Registrable(_destinations[i]).getName();\n registry[name] = _destinations[i];\n emit LogRegistered(_destinations[i], name);\n\n unchecked {\n i++;\n }\n }\n }\n\n /// @inheritdoc IRegistry\n function atomicUpdate(address _newContract) external onlyOwner {\n Registrable(_newContract).register();\n\n bytes32 name = Registrable(_newContract).getName();\n address oldContract = registry[name];\n registry[name] = _newContract;\n\n Registrable(oldContract).unregister();\n\n emit LogRegistered(_newContract, name);\n }\n\n /// @inheritdoc IRegistry\n function requireAndGetAddress(bytes32 name) external view returns (address) {\n address _foundAddress = registry[name];\n if (_foundAddress == address(0)) revert NameNotRegistered();\n\n return _foundAddress;\n }\n\n /// @inheritdoc IRegistry\n function getAddress(bytes32 _bytes) external view returns (address) {\n return registry[_bytes];\n }\n\n /// @inheritdoc IRegistry\n function getAddressByString(string memory _name) public view returns (address) {\n return registry[stringToBytes32(_name)];\n }\n\n /// @inheritdoc IRegistry\n function stringToBytes32(string memory _string) public pure returns (bytes32 result) {\n bytes memory tempEmptyStringTest = bytes(_string);\n\n if (tempEmptyStringTest.length == 0) {\n return 0x0;\n }\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n result := mload(add(_string, 32))\n }\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStatic.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/StakingBankStaticNotSupported.sol\";\n\n/// @dev Because we are using PoA in UMB oracle, staked balance does not matter. What's matter is, if signer is\n/// validator or not. In this case we can optimise `StakingBank` and make it static for better gas performance.\nabstract contract StakingBankStatic is StakingBankStaticNotSupported {\n uint256 public constant ONE = 1e18;\n\n uint256 public immutable NUMBER_OF_VALIDATORS; // solhint-disable-line var-name-mixedcase\n uint256 public immutable TOTAL_SUPPLY; // solhint-disable-line var-name-mixedcase\n\n constructor(uint256 _validatorsCount) {\n NUMBER_OF_VALIDATORS = _validatorsCount;\n TOTAL_SUPPLY = _validatorsCount * ONE;\n\n _assertValidSetup(_validatorsCount);\n }\n\n function balances(address _validator) external view returns (uint256) {\n return _isValidator(_validator) ? ONE : 0;\n }\n\n function verifyValidators(address[] calldata _validators) external view returns (bool) {\n for (uint256 i; i < _validators.length;) {\n if (!_isValidator(_validators[i])) return false;\n unchecked { i++; }\n }\n\n return true;\n }\n\n function getNumberOfValidators() external view returns (uint256) {\n return NUMBER_OF_VALIDATORS;\n }\n\n function getAddresses() external view returns (address[] memory) {\n return _addresses();\n }\n\n function getBalances() external view returns (uint256[] memory allBalances) {\n allBalances = new uint256[](NUMBER_OF_VALIDATORS);\n\n for (uint256 i; i < NUMBER_OF_VALIDATORS;) {\n allBalances[i] = ONE;\n\n unchecked {\n // we will not have enough data to overflow\n i++;\n }\n }\n }\n\n function addresses(uint256 _ix) external view returns (address) {\n return _addresses()[_ix];\n }\n\n function validators(address _id) external view virtual returns (address id, string memory location);\n\n /// @dev to follow ERC20 interface\n function balanceOf(address _account) external view returns (uint256) {\n return _isValidator(_account) ? ONE : 0;\n }\n\n /// @dev to follow ERC20 interface\n function totalSupply() external view returns (uint256) {\n return TOTAL_SUPPLY;\n }\n\n /// @dev to follow Registrable interface\n function getName() external pure returns (bytes32) {\n return \"StakingBank\";\n }\n\n /// @dev to follow Registrable interface\n function register() external pure {\n // there are no requirements atm\n }\n\n /// @dev to follow Registrable interface\n function unregister() external pure {\n // there are no requirements atm\n }\n\n function _addresses() internal view virtual returns (address[] memory);\n\n function _isValidator(address _validator) internal view virtual returns (bool);\n\n function _assertValidSetup(uint256 _validatorsCount) internal view virtual{\n address[] memory list = _addresses();\n require(list.length == _validatorsCount);\n\n for (uint256 i; i < _validatorsCount;) {\n require(_isValidator(list[i]));\n\n unchecked { i ++; }\n }\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticCI.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticCI is StakingBankStatic {\n // 0x87630b2d1de0fbd5044eb6891b3d9d98c34c8d310c852f98550ba774480e47cc\n address public constant VALIDATOR_0 = 0x2fFd013AaA7B5a7DA93336C2251075202b33FB2B;\n // 0x3f1e8b94c70206bf816c1ed0b15ad98bdf225ae4c6e7e4eee6cdbcf706fda2ae\n address public constant VALIDATOR_1 = 0x43158ea338Ff13D0bDa0c3EB969B9EA5a624E7Cc;\n // 0x5da6b84117504d06b5dcd52b990d76965d2882f4e5852eb610bc76e4209b10d7\n address public constant VALIDATOR_2 = 0x9Fd8DD0627b9A32399Fd115c4725C7e17BC40e6d;\n // 0x1e5012671de3332ad0b43661984e94ab0e405bffddc9d3e863055040bab354b8\n address public constant VALIDATOR_3 = 0xa3F3659E469b7aE0b249546338DEdc0b684edB05;\n // 0x0edc1e35ea7701ddac703286674e79f04addbf5d2f6162fabc19d39bd3dc6662\n address public constant VALIDATOR_4 = 0xB98A954B9036DF144d685E910bfbAEC6B33A8d11;\n // 0x23c601ae397441f3ef6f1075dcb0031ff17fb079837beadaf3c84d96c6f3e569\n address public constant VALIDATOR_5 = 0xE5904695748fe4A84b40b3fc79De2277660BD1D3;\n\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.ci.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.ci.umb.network\");\n if (_id == VALIDATOR_2) return (_id, \"https://validator3.ci.umb.network\");\n if (_id == VALIDATOR_3) return (_id, \"https://validator4.ci.umb.network\");\n if (_id == VALIDATOR_4) return (_id, \"https://validator5.ci.umb.network\");\n if (_id == VALIDATOR_5) return (_id, \"https://validator6.ci.umb.network\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n list[2] = VALIDATOR_2;\n list[3] = VALIDATOR_3;\n list[4] = VALIDATOR_4;\n list[5] = VALIDATOR_5;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0\n || _validator == VALIDATOR_1\n || _validator == VALIDATOR_2\n || _validator == VALIDATOR_3\n || _validator == VALIDATOR_4\n || _validator == VALIDATOR_5\n );\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticDev.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticDev is StakingBankStatic {\n address public constant VALIDATOR_0 = 0xDc3eBc37DA53A644D67E5E3b5BA4EEF88D969d5C;\n address public constant VALIDATOR_1 = 0x998cb7821e605cC16b6174e7C50E19ADb2Dd2fB0;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.dev.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.dev.umb.network\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0 || _validator == VALIDATOR_1);\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticLocal.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticLocal is StakingBankStatic {\n address public constant VALIDATOR_0 = 0xeAD9C93b79Ae7C1591b1FB5323BD777E86e150d4;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"localhost\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0);\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticProd.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\ncontract StakingBankStaticProd is StakingBankStatic {\n address public constant VALIDATOR_0 = 0x977Ba523420110e230643B772Fe9cF955e11dA7B;\n address public constant VALIDATOR_1 = 0xe2422b23e52bc13ebA04d7FbB9F332Deb43360fB;\n\n // external order is based on validators submits on AVAX for Apr 2023\n address public constant VALIDATOR_2 = 0x57F404aD75e371c1A539589C1eFCA12e0C6980AD;\n address public constant VALIDATOR_3 = 0xD56C6A4f64E0bD70260472d1DB6Cf5825858CB0d;\n address public constant VALIDATOR_4 = 0x93FdcAB283b0BcAc48157590af482E1CFd6af6aC;\n address public constant VALIDATOR_5 = 0xCd733E06B06083d52fC5867E8E3432aA5c103A38;\n address public constant VALIDATOR_6 = 0x42e210b110c6aa49CdfA7ceF1444Aa4719653111;\n address public constant VALIDATOR_7 = 0x501731c6a69803a53Ec6c3e12f293c247cE1092B;\n address public constant VALIDATOR_8 = 0x8bF9661F1b247522C75DD0FE84355aD2EfF27144;\n address public constant VALIDATOR_9 = 0x281754Ab58391A478B7aA4E7f39991CfB41118c4;\n address public constant VALIDATOR_10 = 0x57A51D5BDcE188c2295fCA3b4687475a54E65A02;\n address public constant VALIDATOR_11 = 0x2F85824B2B38F179E451988670935d315b5b9692;\n address public constant VALIDATOR_12 = 0xA7241994267682de4dE7Ef62f52dc2C783d1784B;\n address public constant VALIDATOR_13 = 0x6eEd457C20603EDAE50C3A112CAA1a9425321bD0;\n address public constant VALIDATOR_14 = 0xC5a7650c2725a7B6A39f15cb9FbffC7af357AFeb;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n // solhint-disable-next-line code-complexity\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.umb.network\");\n if (_id == VALIDATOR_2) return (_id, \"https://umbrella.artemahr.tech\");\n if (_id == VALIDATOR_3) return (_id, \"https://umb.vtabsolutions.com:3030\");\n if (_id == VALIDATOR_4) return (_id, \"https://umbrella.crazywhale.es\");\n if (_id == VALIDATOR_5) return (_id, \"https://umbrella-node.gateomega.com\");\n if (_id == VALIDATOR_6) return (_id, \"https://umb.anorak.technology\");\n if (_id == VALIDATOR_7) return (_id, \"https://umbrella.validator.infstones.io\");\n if (_id == VALIDATOR_8) return (_id, \"https://umb.hashkey.cloud\");\n if (_id == VALIDATOR_9) return (_id, \"http://umbrella.staking4all.org:3000\");\n if (_id == VALIDATOR_10) return (_id, \"http://5.161.78.230:3000\");\n if (_id == VALIDATOR_11) return (_id, \"https://umb-api.staking.rocks\");\n if (_id == VALIDATOR_12) return (_id, \"https://rpc.urbanhq.net\");\n if (_id == VALIDATOR_13) return (_id, \"https://umbrella-node.ankastake.com\");\n if (_id == VALIDATOR_14) return (_id, \"https://umbrella.tchambrella.com\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n list[2] = VALIDATOR_2;\n list[3] = VALIDATOR_3;\n list[4] = VALIDATOR_4;\n list[5] = VALIDATOR_5;\n list[6] = VALIDATOR_6;\n list[7] = VALIDATOR_7;\n list[8] = VALIDATOR_8;\n list[9] = VALIDATOR_9;\n list[10] = VALIDATOR_10;\n list[11] = VALIDATOR_11;\n list[12] = VALIDATOR_12;\n list[13] = VALIDATOR_13;\n list[14] = VALIDATOR_14;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (\n _validator == VALIDATOR_0\n || _validator == VALIDATOR_1\n || _validator == VALIDATOR_2\n || _validator == VALIDATOR_3\n || _validator == VALIDATOR_4\n || _validator == VALIDATOR_5\n || _validator == VALIDATOR_6\n || _validator == VALIDATOR_7\n || _validator == VALIDATOR_8\n || _validator == VALIDATOR_9\n || _validator == VALIDATOR_10\n || _validator == VALIDATOR_11\n || _validator == VALIDATOR_12\n || _validator == VALIDATOR_13\n || _validator == VALIDATOR_14\n );\n }\n}\n" + }, + "contracts/stakingBankStatic/StakingBankStaticSbx.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\n\ncontract StakingBankStaticSbx is StakingBankStatic {\n address public constant VALIDATOR_0 = 0xE3bDa0C6E1fBB111091Dfef6f22a673b20Ea5F50;\n address public constant VALIDATOR_1 = 0xc1773490F00963CBAb3841fc07C1a0796E658Ba2;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.sbx.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.sbx.umb.network\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (_validator == VALIDATOR_0 || _validator == VALIDATOR_1);\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": false, + "runs": 0 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/flattened/avalanche_production__StakingBankStatic.stdandard.json b/flattened/avalanche_production__StakingBankStatic.stdandard.json new file mode 100644 index 00000000..ab623f12 --- /dev/null +++ b/flattened/avalanche_production__StakingBankStatic.stdandard.json @@ -0,0 +1 @@ +{"language":"Solidity","sources":{"@openzeppelin/contracts/token/ERC20/IERC20.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n"},"contracts/interfaces/IStakingBank.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IStakingBank is IERC20 {\n /// @param id address of validator wallet\n /// @param location URL of the validator API\n struct Validator {\n address id;\n string location;\n }\n\n event LogValidatorRegistered(address indexed id);\n event LogValidatorUpdated(address indexed id);\n event LogValidatorRemoved(address indexed id);\n event LogMinAmountForStake(uint256 minAmountForStake);\n\n /// @dev setter for `minAmountForStake`\n function setMinAmountForStake(uint256 _minAmountForStake) external;\n\n /// @dev allows to stake `token` by validators\n /// Validator needs to approve StakingBank beforehand\n /// @param _value amount of tokens to stake\n function stake(uint256 _value) external;\n\n /// @dev notification about approval from `_from` address on UMB token\n /// Staking bank will stake max approved amount from `_from` address\n /// @param _from address which approved token spend for IStakingBank\n function receiveApproval(address _from) external returns (bool success);\n\n /// @dev withdraws stake tokens\n /// it throws, when balance will be less than required minimum for stake\n /// to withdraw all use `exit`\n function withdraw(uint256 _value) external returns (bool success);\n\n /// @dev unstake and withdraw all tokens\n function exit() external returns (bool success);\n\n /// @dev creates (register) new validator\n /// @param _id validator address\n /// @param _location location URL of the validator API\n function create(address _id, string calldata _location) external;\n\n /// @dev removes validator\n /// @param _id validator wallet\n function remove(address _id) external;\n\n /// @dev updates validator location\n /// @param _id validator wallet\n /// @param _location new validator URL\n function update(address _id, string calldata _location) external;\n\n /// @return total number of registered validators (with and without balance)\n function getNumberOfValidators() external view returns (uint256);\n\n /// @dev gets validator address for provided index\n /// @param _ix index in array of list of all validators wallets\n function addresses(uint256 _ix) external view returns (address);\n\n /// @param _id address of validator\n /// @return id address of validator\n /// @return location URL of validator\n function validators(address _id) external view returns (address id, string memory location);\n}\n"},"contracts/interfaces/StakingBankStaticNotSupported.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./IStakingBank.sol\";\n\nabstract contract StakingBankStaticNotSupported is IStakingBank {\n error NotSupported();\n\n function create(address, string calldata) external pure {\n revert NotSupported();\n }\n\n function update(address, string calldata) external pure {\n revert NotSupported();\n }\n\n function remove(address) external pure {\n revert NotSupported();\n }\n\n function transfer(address, uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function transferFrom(address, address, uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function receiveApproval(address) external pure returns (bool) {\n revert NotSupported();\n }\n\n function allowance(address, address) external pure returns (uint256) {\n revert NotSupported();\n }\n\n function approve(address, uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function stake(uint256) external pure {\n revert NotSupported();\n }\n\n function withdraw(uint256) external pure returns (bool) {\n revert NotSupported();\n }\n\n function exit() external pure returns (bool) {\n revert NotSupported();\n }\n\n function setMinAmountForStake(uint256) external pure {\n revert NotSupported();\n }\n}\n"},"contracts/stakingBankStatic/StakingBankStatic.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../interfaces/StakingBankStaticNotSupported.sol\";\n\n/// @dev Because we are using PoA in UMB oracle, staked balance does not matter. What's matter is, if signer is\n/// validator or not. In this case we can optimise `StakingBank` and make it static for better gas performance.\nabstract contract StakingBankStatic is StakingBankStaticNotSupported {\n uint256 public constant ONE = 1e18;\n\n uint256 public immutable NUMBER_OF_VALIDATORS; // solhint-disable-line var-name-mixedcase\n uint256 public immutable TOTAL_SUPPLY; // solhint-disable-line var-name-mixedcase\n\n constructor(uint256 _validatorsCount) {\n NUMBER_OF_VALIDATORS = _validatorsCount;\n TOTAL_SUPPLY = _validatorsCount * ONE;\n\n _assertValidSetup(_validatorsCount);\n }\n\n function balances(address _validator) external view returns (uint256) {\n return _isValidator(_validator) ? ONE : 0;\n }\n\n function verifyValidators(address[] calldata _validators) external view returns (bool) {\n for (uint256 i; i < _validators.length;) {\n if (!_isValidator(_validators[i])) return false;\n unchecked { i++; }\n }\n\n return true;\n }\n\n function getNumberOfValidators() external view returns (uint256) {\n return NUMBER_OF_VALIDATORS;\n }\n\n function getAddresses() external view returns (address[] memory) {\n return _addresses();\n }\n\n function getBalances() external view returns (uint256[] memory allBalances) {\n allBalances = new uint256[](NUMBER_OF_VALIDATORS);\n\n for (uint256 i; i < NUMBER_OF_VALIDATORS;) {\n allBalances[i] = ONE;\n\n unchecked {\n // we will not have enough data to overflow\n i++;\n }\n }\n }\n\n function addresses(uint256 _ix) external view returns (address) {\n return _addresses()[_ix];\n }\n\n function validators(address _id) external view virtual returns (address id, string memory location);\n\n /// @dev to follow ERC20 interface\n function balanceOf(address _account) external view returns (uint256) {\n return _isValidator(_account) ? ONE : 0;\n }\n\n /// @dev to follow ERC20 interface\n function totalSupply() external view returns (uint256) {\n return TOTAL_SUPPLY;\n }\n\n /// @dev to follow Registrable interface\n function getName() external pure returns (bytes32) {\n return \"StakingBank\";\n }\n\n /// @dev to follow Registrable interface\n function register() external pure {\n // there are no requirements atm\n }\n\n /// @dev to follow Registrable interface\n function unregister() external pure {\n // there are no requirements atm\n }\n\n function _addresses() internal view virtual returns (address[] memory);\n\n function _isValidator(address _validator) internal view virtual returns (bool);\n\n function _assertValidSetup(uint256 _validatorsCount) internal view virtual{\n address[] memory list = _addresses();\n require(list.length == _validatorsCount);\n\n for (uint256 i; i < _validatorsCount;) {\n require(_isValidator(list[i]));\n\n unchecked { i ++; }\n }\n }\n}\n"},"contracts/stakingBankStatic/StakingBankStaticProd.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./StakingBankStatic.sol\";\n\ncontract StakingBankStaticProd is StakingBankStatic {\n address public constant VALIDATOR_0 = 0x977Ba523420110e230643B772Fe9cF955e11dA7B;\n address public constant VALIDATOR_1 = 0xe2422b23e52bc13ebA04d7FbB9F332Deb43360fB;\n\n // external order is based on validators submits on AVAX for Apr 2023\n address public constant VALIDATOR_2 = 0x57F404aD75e371c1A539589C1eFCA12e0C6980AD;\n address public constant VALIDATOR_3 = 0xD56C6A4f64E0bD70260472d1DB6Cf5825858CB0d;\n address public constant VALIDATOR_4 = 0x93FdcAB283b0BcAc48157590af482E1CFd6af6aC;\n address public constant VALIDATOR_5 = 0xCd733E06B06083d52fC5867E8E3432aA5c103A38;\n address public constant VALIDATOR_6 = 0x42e210b110c6aa49CdfA7ceF1444Aa4719653111;\n address public constant VALIDATOR_7 = 0x501731c6a69803a53Ec6c3e12f293c247cE1092B;\n address public constant VALIDATOR_8 = 0x8bF9661F1b247522C75DD0FE84355aD2EfF27144;\n address public constant VALIDATOR_9 = 0x281754Ab58391A478B7aA4E7f39991CfB41118c4;\n address public constant VALIDATOR_10 = 0x57A51D5BDcE188c2295fCA3b4687475a54E65A02;\n address public constant VALIDATOR_11 = 0x2F85824B2B38F179E451988670935d315b5b9692;\n address public constant VALIDATOR_12 = 0xA7241994267682de4dE7Ef62f52dc2C783d1784B;\n address public constant VALIDATOR_13 = 0x6eEd457C20603EDAE50C3A112CAA1a9425321bD0;\n address public constant VALIDATOR_14 = 0xC5a7650c2725a7B6A39f15cb9FbffC7af357AFeb;\n\n constructor(uint256 _validatorsCount) StakingBankStatic(_validatorsCount) {}\n\n // solhint-disable-next-line code-complexity\n function validators(address _id) external pure override returns (address id, string memory location) {\n if (_id == VALIDATOR_0) return (_id, \"https://validator.umb.network\");\n if (_id == VALIDATOR_1) return (_id, \"https://validator2.umb.network\");\n if (_id == VALIDATOR_2) return (_id, \"https://umbrella.artemahr.tech\");\n if (_id == VALIDATOR_3) return (_id, \"https://umb.vtabsolutions.com:3030\");\n if (_id == VALIDATOR_4) return (_id, \"https://umbrella.crazywhale.es\");\n if (_id == VALIDATOR_5) return (_id, \"https://umbrella-node.gateomega.com\");\n if (_id == VALIDATOR_6) return (_id, \"https://umb.anorak.technology\");\n if (_id == VALIDATOR_7) return (_id, \"https://umbrella.validator.infstones.io\");\n if (_id == VALIDATOR_8) return (_id, \"https://umb.hashkey.cloud\");\n if (_id == VALIDATOR_9) return (_id, \"http://umbrella.staking4all.org:3000\");\n if (_id == VALIDATOR_10) return (_id, \"http://5.161.78.230:3000\");\n if (_id == VALIDATOR_11) return (_id, \"https://umb-api.staking.rocks\");\n if (_id == VALIDATOR_12) return (_id, \"https://rpc.urbanhq.net\");\n if (_id == VALIDATOR_13) return (_id, \"https://umbrella-node.ankastake.com\");\n if (_id == VALIDATOR_14) return (_id, \"https://umbrella.tchambrella.com\");\n\n return (address(0), \"\");\n }\n\n function _addresses() internal view override returns (address[] memory) {\n address[] memory list = new address[](NUMBER_OF_VALIDATORS);\n\n list[0] = VALIDATOR_0;\n list[1] = VALIDATOR_1;\n list[2] = VALIDATOR_2;\n list[3] = VALIDATOR_3;\n list[4] = VALIDATOR_4;\n list[5] = VALIDATOR_5;\n list[6] = VALIDATOR_6;\n list[7] = VALIDATOR_7;\n list[8] = VALIDATOR_8;\n list[9] = VALIDATOR_9;\n list[10] = VALIDATOR_10;\n list[11] = VALIDATOR_11;\n list[12] = VALIDATOR_12;\n list[13] = VALIDATOR_13;\n list[14] = VALIDATOR_14;\n\n return list;\n }\n\n function _isValidator(address _validator) internal pure override returns (bool) {\n return (\n _validator == VALIDATOR_0\n || _validator == VALIDATOR_1\n || _validator == VALIDATOR_2\n || _validator == VALIDATOR_3\n || _validator == VALIDATOR_4\n || _validator == VALIDATOR_5\n || _validator == VALIDATOR_6\n || _validator == VALIDATOR_7\n || _validator == VALIDATOR_8\n || _validator == VALIDATOR_9\n || _validator == VALIDATOR_10\n || _validator == VALIDATOR_11\n || _validator == VALIDATOR_12\n || _validator == VALIDATOR_13\n || _validator == VALIDATOR_14\n );\n }\n}\n"}},"settings":{"optimizer":{"enabled":false,"runs":0},"outputSelection":{"contracts/stakingBankStatic/StakingBankStaticProd.sol":{"StakingBankStaticProd":["*"]},"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","metadata","devdoc","userdoc","storageLayout","evm.gasEstimates"],"":["ast"]}},"metadata":{"useLiteralContent":true},"libraries":{}}} \ No newline at end of file diff --git a/package.json b/package.json index 9b85f1e0..c0dd5607 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "phoenix", - "version": "4.14.0", + "version": "4.15.0", "description": "A proof-of-stake contract for minting sidechain blocks.", "engines": { "node": "^14.17.0 || >=16.0.0" diff --git a/tasks/_helpers/registerChain.ts b/tasks/_helpers/registerChain.ts index 1bfa6361..35deb1f0 100644 --- a/tasks/_helpers/registerChain.ts +++ b/tasks/_helpers/registerChain.ts @@ -4,7 +4,7 @@ import { CHAIN, FOREIGN_CHAIN, REGISTRY } from '../../constants'; import { BaseChain, Registry__factory } from '../../typechain'; import { resolveChainName } from './resolveChainName'; import { Contract, ethers } from 'ethers'; -import { isMasterChain } from '../../constants/networks'; +import { BNB_PRODUCTION, isMasterChain } from '../../constants/networks'; import { ChainStatus } from '../../test/types/ChainStatus'; import { confirmations } from './confirmations'; @@ -120,11 +120,13 @@ export const registerChain = async (hre: HardhatRuntimeEnvironment) => { throw e; } - if ((e as Error).message.includes('transaction underpriced')) { + const hasAtomicUpdate = ![BNB_PRODUCTION].includes(hre.network.name); + + if (hasAtomicUpdate && (e as Error).message.includes('transaction underpriced')) { throw e; } - if ((e as Error).message.includes('cannot estimate gas')) { + if (hasAtomicUpdate && (e as Error).message.includes('cannot estimate gas')) { throw e; } diff --git a/tasks/lineaVerifyCode.ts b/tasks/lineaVerifyCode.ts index 4d12927b..80d64557 100644 --- a/tasks/lineaVerifyCode.ts +++ b/tasks/lineaVerifyCode.ts @@ -1,7 +1,13 @@ import { task } from 'hardhat/config'; import fs from 'fs'; import axios from 'axios'; -import { AVALANCHE_SANDBOX, AVALANCHE_STAGING, LINEA_SANDBOX, POLYGON_SANDBOX } from '../constants/networks'; +import { + AVALANCHE_PRODUCTION, + AVALANCHE_SANDBOX, + AVALANCHE_STAGING, + LINEA_SANDBOX, + POLYGON_SANDBOX, +} from '../constants/networks'; task('linea-verify', 'task for debugging') .addOptionalParam('name') @@ -24,6 +30,13 @@ task('linea-verify', 'task for debugging') ); break; + case AVALANCHE_PRODUCTION: + response = await axios.get( + 'https://api.snowtrace.io/api?' + + `module=contract&action=getsourcecode&address=${address}&apikey=${AVASCAN_API}`, + ); + break; + case LINEA_SANDBOX: response = await axios.get( 'https://api-testnet.lineascan.build/api?' + diff --git a/tasks/registerUmbrellaFeeds.ts b/tasks/registerUmbrellaFeeds.ts index b2c04f1e..8d84fe5e 100644 --- a/tasks/registerUmbrellaFeeds.ts +++ b/tasks/registerUmbrellaFeeds.ts @@ -45,31 +45,21 @@ task('registerUmbrellaFeeds', 'UmbrellaFeeds registration') const nonce = await deployer.getTransactionCount('latest'); console.log({ nonce, from: deployer.address }); - if (oldExists) { - const oldUmbrellaFeeds = UmbrellaFeeds__factory.connect(inRegistry, deployer); - - const price = await oldUmbrellaFeeds.getPriceDataByName(taskArgs.destroy); - - if (oldExists && price.timestamp == 0) { - if (taskArgs.destroy != 'any') throw new Error(`provided key ${taskArgs.destroy} is empty in ${inRegistry}`); - } else { - console.log(`key ${taskArgs.destroy} exists so old contract ${inRegistry} will be destroyed`); - } - } - const tx = await registry.importContracts([newUmbrellaFeeds.address], { nonce, gasPrice: hre.network.config.gasPrice == 'auto' ? undefined : hre.network.config.gasPrice, }); console.log(`importContracts tx #${tx.nonce} ${tx.hash}`); + await tx.wait(1); - if (oldExists) { + if (oldExists && taskArgs.destroy != undefined) { + console.log(`old contract ${inRegistry} will be destroyed`); const oldUmbrellaFeeds = UmbrellaFeeds__factory.connect(inRegistry, deployer); const tx2 = await oldUmbrellaFeeds.destroy(taskArgs.destroy, { nonce: nonce + 1, - gasPrice: hre.network.config.gasPrice == 'auto' ? undefined : hre.network.config.gasPrice, + gasLPrice: hre.network.config.gasPrice == 'auto' ? undefined : hre.network.config.gasPrice, }); console.log(`destroy tx #${tx2.nonce} ${tx2.hash}`);