diff --git a/constants/networks.ts b/constants/networks.ts index 989eb2b..9a8f9b2 100644 --- a/constants/networks.ts +++ b/constants/networks.ts @@ -12,6 +12,7 @@ export const _5IRE_SANDBOX = '5ire_sandbox'; export const LOCALHOST = 'localhost'; export const HARDHAT = 'hardhat'; +export const DIONE_STAGING = 'dione_staging'; export const _5IRE_STAGING = '5ire_staging'; export const LINEA_STAGING = 'linea_staging'; export const BASE_STAGING = 'base_staging'; diff --git a/constants/providers.ts b/constants/providers.ts index 5a5728a..d850dc0 100644 --- a/constants/providers.ts +++ b/constants/providers.ts @@ -19,6 +19,7 @@ import { BNB_STAGING, BOB_PRODUCTION, BOB_STAGING, + DIONE_STAGING, ETH_PRODUCTION, ETH_SANDBOX, ETH_SEPOLIA, @@ -107,6 +108,11 @@ const _5fireTestnetProviderData: ProviderData = { chainId: chainId(997), }; +const dioneTestnetProviderData: ProviderData = { + url: 'https://testnode.dioneprotocol.com/ext/bc/D/rpc', + chainId: chainId(131313), +}; + // https://docs.gobob.xyz/docs/build/getting-started/networks const bobTestnetProviderData: ProviderData = { url: `https://bob-sepolia.blastapi.io/${BLAST_RPC_ID}`, @@ -220,6 +226,9 @@ const baseMainnetProviderData: ProviderData = { const resolveProviderData = (networkName: string): ProviderData => { switch (networkName) { + case DIONE_STAGING: + return dioneTestnetProviderData; + case _5IRE_STAGING: case _5IRE_SANDBOX: return _5fireTestnetProviderData; diff --git a/deploy/_helpers/onChainSupportedBlockchains.ts b/deploy/_helpers/onChainSupportedBlockchains.ts index be2cea5..5c9a17c 100644 --- a/deploy/_helpers/onChainSupportedBlockchains.ts +++ b/deploy/_helpers/onChainSupportedBlockchains.ts @@ -17,6 +17,7 @@ export function onChainSupportedBlockchains(hre: HardhatRuntimeEnvironment): boo if (hre.network.name.includes('zk_link_')) return true; if (hre.network.name.includes('bob_')) return true; if (hre.network.name.includes('_5ire')) return true; + if (hre.network.name.includes('dione')) return true; return false; } diff --git a/deployments/dione_staging/.chainId b/deployments/dione_staging/.chainId new file mode 100644 index 0000000..007cd79 --- /dev/null +++ b/deployments/dione_staging/.chainId @@ -0,0 +1 @@ +131313 \ No newline at end of file diff --git a/deployments/dione_staging/Registry.json b/deployments/dione_staging/Registry.json new file mode 100644 index 0000000..4136dbd --- /dev/null +++ b/deployments/dione_staging/Registry.json @@ -0,0 +1,373 @@ +{ + "address": "0x92010E763d476A732021191562134c488ca92a1F", + "abi": [ + { + "inputs": [], + "name": "ArraysDataDoNotMatch", + "type": "error" + }, + { + "inputs": [], + "name": "NameNotRegistered", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "name", + "type": "bytes32" + } + ], + "name": "LogRegistered", + "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": [ + { + "internalType": "address", + "name": "_newContract", + "type": "address" + } + ], + "name": "atomicUpdate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_bytes", + "type": "bytes32" + } + ], + "name": "getAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_name", + "type": "string" + } + ], + "name": "getAddressByString", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "_names", + "type": "bytes32[]" + }, + { + "internalType": "address[]", + "name": "_destinations", + "type": "address[]" + } + ], + "name": "importAddresses", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_destinations", + "type": "address[]" + } + ], + "name": "importContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "registry", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "name", + "type": "bytes32" + } + ], + "name": "requireAndGetAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_string", + "type": "string" + } + ], + "name": "stringToBytes32", + "outputs": [ + { + "internalType": "bytes32", + "name": "result", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x9eebb92eb1cbaa6c40514d526c9c5cbb6b346a65095023833eac5fa2216facfb", + "receipt": { + "to": null, + "from": "0x66f13FDceed822E74b6a1e08e082Fa699fF36454", + "contractAddress": "0x92010E763d476A732021191562134c488ca92a1F", + "transactionIndex": 0, + "gasUsed": "1123496", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000200000000800000000000000000000000000000000000000000000000000000000000000000000000000001000000000000040000000000000000000000020000000000000000000900000000000000000000000000000000400000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x1286df2f2f622a98b2108a42eba706230f287106059bbfc72b9a9e753c5586b9", + "transactionHash": "0x9eebb92eb1cbaa6c40514d526c9c5cbb6b346a65095023833eac5fa2216facfb", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 782519, + "transactionHash": "0x9eebb92eb1cbaa6c40514d526c9c5cbb6b346a65095023833eac5fa2216facfb", + "address": "0x92010E763d476A732021191562134c488ca92a1F", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000066f13fdceed822e74b6a1e08e082fa699ff36454" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x1286df2f2f622a98b2108a42eba706230f287106059bbfc72b9a9e753c5586b9" + } + ], + "blockNumber": 782519, + "cumulativeGasUsed": "1123496", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "7f9517721aff9c6260eb58dca9f69725", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"ArraysDataDoNotMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NameNotRegistered\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"name\",\"type\":\"bytes32\"}],\"name\":\"LogRegistered\",\"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\":[{\"internalType\":\"address\",\"name\":\"_newContract\",\"type\":\"address\"}],\"name\":\"atomicUpdate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_bytes\",\"type\":\"bytes32\"}],\"name\":\"getAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"getAddressByString\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_names\",\"type\":\"bytes32[]\"},{\"internalType\":\"address[]\",\"name\":\"_destinations\",\"type\":\"address[]\"}],\"name\":\"importAddresses\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_destinations\",\"type\":\"address[]\"}],\"name\":\"importContracts\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"registry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"name\",\"type\":\"bytes32\"}],\"name\":\"requireAndGetAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_string\",\"type\":\"string\"}],\"name\":\"stringToBytes32\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"result\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"contracts registry protocol uses this registry to fetch current contract addresses\",\"kind\":\"dev\",\"methods\":{\"atomicUpdate(address)\":{\"details\":\"this method ensure, that old and new contract is aware of it state in registry Note: BSC registry does not have this method. This method was introduced in later stage.\",\"params\":{\"_newContract\":\"address of contract that will replace old one\"}},\"getAddress(bytes32)\":{\"params\":{\"name\":\"contract name in a form of bytes32\"},\"returns\":{\"_0\":\"contract address registered under provided name\"}},\"getAddressByString(string)\":{\"params\":{\"_name\":\"contract name\"},\"returns\":{\"_0\":\"contract address assigned to the name or address(0) if not exists\"}},\"importAddresses(bytes32[],address[])\":{\"details\":\"imports new contract addresses and override old addresses, if they exist under provided name This method can be used for contracts that for some reason do not have `getName` method\",\"params\":{\"_destinations\":\"array of contract addresses\",\"_names\":\"array of contract names that we want to register\"}},\"importContracts(address[])\":{\"details\":\"imports new contracts and override old addresses, if they exist. Names of contracts are fetched directly from each contract by calling `getName`\",\"params\":{\"_destinations\":\"array of contract addresses\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"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.\"},\"requireAndGetAddress(bytes32)\":{\"details\":\"similar to `getAddress` but throws when contract name not exists\",\"params\":{\"name\":\"contract name\"},\"returns\":{\"_0\":\"contract address registered under provided name or throws, if does not exists\"}},\"stringToBytes32(string)\":{\"details\":\"helper method that converts string to bytes32, you can use to to generate contract name\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"registry(bytes32)\":{\"notice\":\"name => contract address\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Registry.sol\":\"Registry\"},\"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\"},\"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/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": "0x608060405234801561001057600080fd5b5061002d61002261003260201b60201c565b61003a60201b60201c565b6100fe565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6112ed8061010d6000396000f3fe608060405234801561001057600080fd5b50600436106100995760003560e01c806310b689011461009e57806321f8a721146100ba57806346bcb49d146100ea578063648642e91461011a578063715018a6146101365780637ef50298146101405780638da5cb5b14610170578063ab0b8f771461018e578063cfb51928146101aa578063e8f98f88146101da578063f2fde38b1461020a575b600080fd5b6100b860048036038101906100b39190610d47565b610226565b005b6100d460048036038101906100cf9190610dca565b61044b565b6040516100e19190610e38565b60405180910390f35b61010460048036038101906100ff9190610dca565b610488565b6040516101119190610e38565b60405180910390f35b610134600480360381019061012f9190610e7f565b610530565b005b61013e6107bc565b005b61015a60048036038101906101559190610dca565b610844565b6040516101679190610e38565b60405180910390f35b610178610877565b6040516101859190610e38565b60405180910390f35b6101a860048036038101906101a39190610f02565b6108a0565b005b6101c460048036038101906101bf91906110c4565b610a9d565b6040516101d1919061111c565b60405180910390f35b6101f460048036038101906101ef91906110c4565b610ac6565b6040516102019190610e38565b60405180910390f35b610224600480360381019061021f9190610e7f565b610b0b565b005b61022e610c02565b73ffffffffffffffffffffffffffffffffffffffff1661024c610877565b73ffffffffffffffffffffffffffffffffffffffff16146102a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161029990611194565b60405180910390fd5b60005b828290508110156104465760008383838181106102c5576102c46111b4565b5b90506020020160208101906102da9190610e7f565b73ffffffffffffffffffffffffffffffffffffffff166317d7de7c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610324573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061034891906111f8565b905083838381811061035d5761035c6111b4565b5b90506020020160208101906103729190610e7f565b6001600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508383838181106103d6576103d56111b4565b5b90506020020160208101906103eb9190610e7f565b73ffffffffffffffffffffffffffffffffffffffff167f528ecde2b2a965b3d69f80eb4775d121bf5fe485f9bfc184b5b789a90065bb0482604051610430919061111c565b60405180910390a28180600101925050506102a5565b505050565b60006001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000806001600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610527576040517f31aef0e500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80915050919050565b610538610c02565b73ffffffffffffffffffffffffffffffffffffffff16610556610877565b73ffffffffffffffffffffffffffffffffffffffff16146105ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105a390611194565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16631aa3a0086040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156105f457600080fd5b505af1158015610608573d6000803e3d6000fd5b5050505060008173ffffffffffffffffffffffffffffffffffffffff166317d7de7c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610659573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061067d91906111f8565b905060006001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050826001600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff1663e79a198f6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561075157600080fd5b505af1158015610765573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff167f528ecde2b2a965b3d69f80eb4775d121bf5fe485f9bfc184b5b789a90065bb04836040516107af919061111c565b60405180910390a2505050565b6107c4610c02565b73ffffffffffffffffffffffffffffffffffffffff166107e2610877565b73ffffffffffffffffffffffffffffffffffffffff1614610838576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161082f90611194565b60405180910390fd5b6108426000610c0a565b565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6108a8610c02565b73ffffffffffffffffffffffffffffffffffffffff166108c6610877565b73ffffffffffffffffffffffffffffffffffffffff161461091c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161091390611194565b60405180910390fd5b81819050848490501461095b576040517f0cf7902300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b84849050811015610a965782828281811061097c5761097b6111b4565b5b90506020020160208101906109919190610e7f565b600160008787858181106109a8576109a76111b4565b5b90506020020135815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550828282818110610a0e57610a0d6111b4565b5b9050602002016020810190610a239190610e7f565b73ffffffffffffffffffffffffffffffffffffffff167f528ecde2b2a965b3d69f80eb4775d121bf5fe485f9bfc184b5b789a90065bb04868684818110610a6d57610a6c6111b4565b5b90506020020135604051610a81919061111c565b60405180910390a2808060010191505061095e565b5050505050565b6000808290506000815103610ab8576000801b915050610ac1565b60208301519150505b919050565b600060016000610ad584610a9d565b815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b610b13610c02565b73ffffffffffffffffffffffffffffffffffffffff16610b31610877565b73ffffffffffffffffffffffffffffffffffffffff1614610b87576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b7e90611194565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610bf6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bed90611297565b60405180910390fd5b610bff81610c0a565b50565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b60008083601f840112610d0757610d06610ce2565b5b8235905067ffffffffffffffff811115610d2457610d23610ce7565b5b602083019150836020820283011115610d4057610d3f610cec565b5b9250929050565b60008060208385031215610d5e57610d5d610cd8565b5b600083013567ffffffffffffffff811115610d7c57610d7b610cdd565b5b610d8885828601610cf1565b92509250509250929050565b6000819050919050565b610da781610d94565b8114610db257600080fd5b50565b600081359050610dc481610d9e565b92915050565b600060208284031215610de057610ddf610cd8565b5b6000610dee84828501610db5565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610e2282610df7565b9050919050565b610e3281610e17565b82525050565b6000602082019050610e4d6000830184610e29565b92915050565b610e5c81610e17565b8114610e6757600080fd5b50565b600081359050610e7981610e53565b92915050565b600060208284031215610e9557610e94610cd8565b5b6000610ea384828501610e6a565b91505092915050565b60008083601f840112610ec257610ec1610ce2565b5b8235905067ffffffffffffffff811115610edf57610ede610ce7565b5b602083019150836020820283011115610efb57610efa610cec565b5b9250929050565b60008060008060408587031215610f1c57610f1b610cd8565b5b600085013567ffffffffffffffff811115610f3a57610f39610cdd565b5b610f4687828801610eac565b9450945050602085013567ffffffffffffffff811115610f6957610f68610cdd565b5b610f7587828801610cf1565b925092505092959194509250565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610fd182610f88565b810181811067ffffffffffffffff82111715610ff057610fef610f99565b5b80604052505050565b6000611003610cce565b905061100f8282610fc8565b919050565b600067ffffffffffffffff82111561102f5761102e610f99565b5b61103882610f88565b9050602081019050919050565b82818337600083830152505050565b600061106761106284611014565b610ff9565b90508281526020810184848401111561108357611082610f83565b5b61108e848285611045565b509392505050565b600082601f8301126110ab576110aa610ce2565b5b81356110bb848260208601611054565b91505092915050565b6000602082840312156110da576110d9610cd8565b5b600082013567ffffffffffffffff8111156110f8576110f7610cdd565b5b61110484828501611096565b91505092915050565b61111681610d94565b82525050565b6000602082019050611131600083018461110d565b92915050565b600082825260208201905092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600061117e602083611137565b915061118982611148565b602082019050919050565b600060208201905081810360008301526111ad81611171565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000815190506111f281610d9e565b92915050565b60006020828403121561120e5761120d610cd8565b5b600061121c848285016111e3565b91505092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000611281602683611137565b915061128c82611225565b604082019050919050565b600060208201905081810360008301526112b081611274565b905091905056fea264697066735822122009a8c52588ce3f4b7f085944c80e84a74a2841020cdae529f53f14ecb1c8003064736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100995760003560e01c806310b689011461009e57806321f8a721146100ba57806346bcb49d146100ea578063648642e91461011a578063715018a6146101365780637ef50298146101405780638da5cb5b14610170578063ab0b8f771461018e578063cfb51928146101aa578063e8f98f88146101da578063f2fde38b1461020a575b600080fd5b6100b860048036038101906100b39190610d47565b610226565b005b6100d460048036038101906100cf9190610dca565b61044b565b6040516100e19190610e38565b60405180910390f35b61010460048036038101906100ff9190610dca565b610488565b6040516101119190610e38565b60405180910390f35b610134600480360381019061012f9190610e7f565b610530565b005b61013e6107bc565b005b61015a60048036038101906101559190610dca565b610844565b6040516101679190610e38565b60405180910390f35b610178610877565b6040516101859190610e38565b60405180910390f35b6101a860048036038101906101a39190610f02565b6108a0565b005b6101c460048036038101906101bf91906110c4565b610a9d565b6040516101d1919061111c565b60405180910390f35b6101f460048036038101906101ef91906110c4565b610ac6565b6040516102019190610e38565b60405180910390f35b610224600480360381019061021f9190610e7f565b610b0b565b005b61022e610c02565b73ffffffffffffffffffffffffffffffffffffffff1661024c610877565b73ffffffffffffffffffffffffffffffffffffffff16146102a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161029990611194565b60405180910390fd5b60005b828290508110156104465760008383838181106102c5576102c46111b4565b5b90506020020160208101906102da9190610e7f565b73ffffffffffffffffffffffffffffffffffffffff166317d7de7c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610324573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061034891906111f8565b905083838381811061035d5761035c6111b4565b5b90506020020160208101906103729190610e7f565b6001600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508383838181106103d6576103d56111b4565b5b90506020020160208101906103eb9190610e7f565b73ffffffffffffffffffffffffffffffffffffffff167f528ecde2b2a965b3d69f80eb4775d121bf5fe485f9bfc184b5b789a90065bb0482604051610430919061111c565b60405180910390a28180600101925050506102a5565b505050565b60006001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000806001600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610527576040517f31aef0e500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80915050919050565b610538610c02565b73ffffffffffffffffffffffffffffffffffffffff16610556610877565b73ffffffffffffffffffffffffffffffffffffffff16146105ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105a390611194565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16631aa3a0086040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156105f457600080fd5b505af1158015610608573d6000803e3d6000fd5b5050505060008173ffffffffffffffffffffffffffffffffffffffff166317d7de7c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610659573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061067d91906111f8565b905060006001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050826001600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff1663e79a198f6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561075157600080fd5b505af1158015610765573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff167f528ecde2b2a965b3d69f80eb4775d121bf5fe485f9bfc184b5b789a90065bb04836040516107af919061111c565b60405180910390a2505050565b6107c4610c02565b73ffffffffffffffffffffffffffffffffffffffff166107e2610877565b73ffffffffffffffffffffffffffffffffffffffff1614610838576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161082f90611194565b60405180910390fd5b6108426000610c0a565b565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6108a8610c02565b73ffffffffffffffffffffffffffffffffffffffff166108c6610877565b73ffffffffffffffffffffffffffffffffffffffff161461091c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161091390611194565b60405180910390fd5b81819050848490501461095b576040517f0cf7902300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b84849050811015610a965782828281811061097c5761097b6111b4565b5b90506020020160208101906109919190610e7f565b600160008787858181106109a8576109a76111b4565b5b90506020020135815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550828282818110610a0e57610a0d6111b4565b5b9050602002016020810190610a239190610e7f565b73ffffffffffffffffffffffffffffffffffffffff167f528ecde2b2a965b3d69f80eb4775d121bf5fe485f9bfc184b5b789a90065bb04868684818110610a6d57610a6c6111b4565b5b90506020020135604051610a81919061111c565b60405180910390a2808060010191505061095e565b5050505050565b6000808290506000815103610ab8576000801b915050610ac1565b60208301519150505b919050565b600060016000610ad584610a9d565b815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b610b13610c02565b73ffffffffffffffffffffffffffffffffffffffff16610b31610877565b73ffffffffffffffffffffffffffffffffffffffff1614610b87576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b7e90611194565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610bf6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bed90611297565b60405180910390fd5b610bff81610c0a565b50565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b60008083601f840112610d0757610d06610ce2565b5b8235905067ffffffffffffffff811115610d2457610d23610ce7565b5b602083019150836020820283011115610d4057610d3f610cec565b5b9250929050565b60008060208385031215610d5e57610d5d610cd8565b5b600083013567ffffffffffffffff811115610d7c57610d7b610cdd565b5b610d8885828601610cf1565b92509250509250929050565b6000819050919050565b610da781610d94565b8114610db257600080fd5b50565b600081359050610dc481610d9e565b92915050565b600060208284031215610de057610ddf610cd8565b5b6000610dee84828501610db5565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610e2282610df7565b9050919050565b610e3281610e17565b82525050565b6000602082019050610e4d6000830184610e29565b92915050565b610e5c81610e17565b8114610e6757600080fd5b50565b600081359050610e7981610e53565b92915050565b600060208284031215610e9557610e94610cd8565b5b6000610ea384828501610e6a565b91505092915050565b60008083601f840112610ec257610ec1610ce2565b5b8235905067ffffffffffffffff811115610edf57610ede610ce7565b5b602083019150836020820283011115610efb57610efa610cec565b5b9250929050565b60008060008060408587031215610f1c57610f1b610cd8565b5b600085013567ffffffffffffffff811115610f3a57610f39610cdd565b5b610f4687828801610eac565b9450945050602085013567ffffffffffffffff811115610f6957610f68610cdd565b5b610f7587828801610cf1565b925092505092959194509250565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610fd182610f88565b810181811067ffffffffffffffff82111715610ff057610fef610f99565b5b80604052505050565b6000611003610cce565b905061100f8282610fc8565b919050565b600067ffffffffffffffff82111561102f5761102e610f99565b5b61103882610f88565b9050602081019050919050565b82818337600083830152505050565b600061106761106284611014565b610ff9565b90508281526020810184848401111561108357611082610f83565b5b61108e848285611045565b509392505050565b600082601f8301126110ab576110aa610ce2565b5b81356110bb848260208601611054565b91505092915050565b6000602082840312156110da576110d9610cd8565b5b600082013567ffffffffffffffff8111156110f8576110f7610cdd565b5b61110484828501611096565b91505092915050565b61111681610d94565b82525050565b6000602082019050611131600083018461110d565b92915050565b600082825260208201905092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600061117e602083611137565b915061118982611148565b602082019050919050565b600060208201905081810360008301526111ad81611171565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000815190506111f281610d9e565b92915050565b60006020828403121561120e5761120d610cd8565b5b600061121c848285016111e3565b91505092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000611281602683611137565b915061128c82611225565b604082019050919050565b600060208201905081810360008301526112b081611274565b905091905056fea264697066735822122009a8c52588ce3f4b7f085944c80e84a74a2841020cdae529f53f14ecb1c8003064736f6c634300080d0033", + "devdoc": { + "details": "contracts registry protocol uses this registry to fetch current contract addresses", + "kind": "dev", + "methods": { + "atomicUpdate(address)": { + "details": "this method ensure, that old and new contract is aware of it state in registry Note: BSC registry does not have this method. This method was introduced in later stage.", + "params": { + "_newContract": "address of contract that will replace old one" + } + }, + "getAddress(bytes32)": { + "params": { + "name": "contract name in a form of bytes32" + }, + "returns": { + "_0": "contract address registered under provided name" + } + }, + "getAddressByString(string)": { + "params": { + "_name": "contract name" + }, + "returns": { + "_0": "contract address assigned to the name or address(0) if not exists" + } + }, + "importAddresses(bytes32[],address[])": { + "details": "imports new contract addresses and override old addresses, if they exist under provided name This method can be used for contracts that for some reason do not have `getName` method", + "params": { + "_destinations": "array of contract addresses", + "_names": "array of contract names that we want to register" + } + }, + "importContracts(address[])": { + "details": "imports new contracts and override old addresses, if they exist. Names of contracts are fetched directly from each contract by calling `getName`", + "params": { + "_destinations": "array of contract addresses" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "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." + }, + "requireAndGetAddress(bytes32)": { + "details": "similar to `getAddress` but throws when contract name not exists", + "params": { + "name": "contract name" + }, + "returns": { + "_0": "contract address registered under provided name or throws, if does not exists" + } + }, + "stringToBytes32(string)": { + "details": "helper method that converts string to bytes32, you can use to to generate contract name" + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "registry(bytes32)": { + "notice": "name => contract address" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/Registry.sol:Registry", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 2767, + "contract": "contracts/Registry.sol:Registry", + "label": "registry", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes32,t_address)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_address)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => address)", + "numberOfBytes": "32", + "value": "t_address" + } + } + } +} \ No newline at end of file diff --git a/deployments/dione_staging/StakingBankStatic.json b/deployments/dione_staging/StakingBankStatic.json new file mode 100644 index 0000000..eb713c5 --- /dev/null +++ b/deployments/dione_staging/StakingBankStatic.json @@ -0,0 +1,671 @@ +{ + "address": "0x97e8922eac4fa07e958667E3e7AEa7a7fe3eC9f6", + "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": [ + { + "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" + } + ], + "transactionHash": "0x42afa489c459daa2c00eb1f4c591216dc89843c42010397b209a0a3166c8e410", + "receipt": { + "to": null, + "from": "0x66f13FDceed822E74b6a1e08e082Fa699fF36454", + "contractAddress": "0x97e8922eac4fa07e958667E3e7AEa7a7fe3eC9f6", + "transactionIndex": 0, + "gasUsed": "1202084", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc42d2c5289ab29ee2919ab4d19a791be823f12c3a0f942539f27707e1613afc8", + "transactionHash": "0x42afa489c459daa2c00eb1f4c591216dc89843c42010397b209a0a3166c8e410", + "logs": [], + "blockNumber": 782520, + "cumulativeGasUsed": "1202084", + "status": 1, + "byzantium": true + }, + "args": [ + 2 + ], + "numDeployments": 1, + "solcInputHash": "7f9517721aff9c6260eb58dca9f69725", + "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\":[{\"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/StakingBankStaticDev.sol\":\"StakingBankStaticDev\"},\"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/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\",\"keccak256\":\"0x98cfecb68a2d37b30a35b1fffcff56b61f8bd90867532a8d7daa9ea85d7ee031\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c06040523480156200001157600080fd5b50604051620018f1380380620018f18339818101604052810190620000379190620002ee565b808060808181525050670de0b6b3a7640000816200005691906200034f565b60a081815250506200006e816200007660201b60201c565b50506200040e565b600062000088620000ef60201b60201c565b9050818151146200009857600080fd5b60005b82811015620000ea57620000d2828281518110620000be57620000bd620003b0565b5b60200260200101516200021760201b60201c565b620000dc57600080fd5b80806001019150506200009b565b505050565b6060600060805167ffffffffffffffff811115620001125762000111620003df565b5b604051908082528060200260200182016040528015620001415781602001602082028036833780820191505090505b50905073dc3ebc37da53a644d67e5e3b5ba4eef88d969d5c8160008151811062000170576200016f620003b0565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073998cb7821e605cc16b6174e7c50e19adb2dd2fb081600181518110620001d657620001d5620003b0565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600073dc3ebc37da53a644d67e5e3b5ba4eef88d969d5c73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480620002a7575073998cb7821e605cc16b6174e7c50e19adb2dd2fb073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b600080fd5b6000819050919050565b620002c881620002b3565b8114620002d457600080fd5b50565b600081519050620002e881620002bd565b92915050565b600060208284031215620003075762000306620002ae565b5b60006200031784828501620002d7565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006200035c82620002b3565b91506200036983620002b3565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615620003a557620003a462000320565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60805160a05161149a62000457600039600081816106c301526108b5015260008181610562015281816105d0015281816108db015281816109cc0152610c13015261149a6000f3fe608060405234801561001057600080fd5b506004361061015e5760003560e01c8062113e0814610163578063095ea7b3146101815780630db18e37146101b157806317d7de7c146101e157806318160ddd146101ff5780631aa3a0081461021d5780631d4f9ce01461022757806323b872dd1461025757806327e235e31461028757806329092d0e146102b75780632e1a7d4d146102d3578063411ff4971461030357806352b41e351461032157806370a082311461033d578063838e7c3a1461036d578063902d55a5146103895780639031d913146103a75780639f0e9484146103c5578063a15ab08d146103e3578063a39fac12146103ff578063a694fc3a1461041d578063a9059cbb14610439578063c2ee3a0814610469578063db73177714610487578063dd62ed3e146104a5578063e79a198f146104d5578063e9fad8ee146104df578063edf26d9b146104fd578063fa52c7d81461052d575b600080fd5b61016b61055e565b6040516101789190610e11565b60405180910390f35b61019b60048036038101906101969190610ec7565b61062f565b6040516101a89190610f22565b60405180910390f35b6101cb60048036038101906101c69190610f3d565b610663565b6040516101d89190610f22565b60405180910390f35b6101e9610697565b6040516101f69190610f83565b60405180910390f35b6102076106bf565b6040516102149190610fad565b60405180910390f35b6102256106e7565b005b610241600480360381019061023c919061102d565b6106e9565b60405161024e9190610f22565b60405180910390f35b610271600480360381019061026c919061107a565b61074f565b60405161027e9190610f22565b60405180910390f35b6102a1600480360381019061029c9190610f3d565b610783565b6040516102ae9190610fad565b60405180910390f35b6102d160048036038101906102cc9190610f3d565b6107aa565b005b6102ed60048036038101906102e891906110cd565b6107dc565b6040516102fa9190610f22565b60405180910390f35b61030b610810565b6040516103189190611109565b60405180910390f35b61033b600480360381019061033691906110cd565b610828565b005b61035760048036038101906103529190610f3d565b61085a565b6040516103649190610fad565b60405180910390f35b6103876004803603810190610382919061117a565b610881565b005b6103916108b3565b60405161039e9190610fad565b60405180910390f35b6103af6108d7565b6040516103bc9190610fad565b60405180910390f35b6103cd6108ff565b6040516103da9190611109565b60405180910390f35b6103fd60048036038101906103f8919061117a565b610917565b005b610407610949565b6040516104149190611298565b60405180910390f35b610437600480360381019061043291906110cd565b610958565b005b610453600480360381019061044e9190610ec7565b61098a565b6040516104609190610f22565b60405180910390f35b6104716109be565b60405161047e9190610fad565b60405180910390f35b61048f6109ca565b60405161049c9190610fad565b60405180910390f35b6104bf60048036038101906104ba91906112ba565b6109ee565b6040516104cc9190610fad565b60405180910390f35b6104dd610a22565b005b6104e7610a24565b6040516104f49190610f22565b60405180910390f35b610517600480360381019061051291906110cd565b610a58565b6040516105249190611109565b60405180910390f35b61054760048036038101906105429190610f3d565b610a83565b604051610555929190611393565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff81111561059a576105996113c3565b5b6040519080825280602002602001820160405280156105c85781602001602082028036833780820191505090505b50905060005b7f000000000000000000000000000000000000000000000000000000000000000081101561062b57670de0b6b3a7640000828281518110610612576106116113f2565b5b60200260200101818152505080806001019150506105ce565b5090565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b838390508110156107435761072884848381811061070e5761070d6113f2565b5b90506020020160208101906107239190610f3d565b610b77565b610736576000915050610749565b80806001019150506106ed565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061078e82610b77565b6107995760006107a3565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73998cb7821e605cc16b6174e7c50e19adb2dd2fb081565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061086582610b77565b61087057600061087a565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b73dc3ebc37da53a644d67e5e3b5ba4eef88d969d5c81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610953610c0d565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a62610c0d565b8281518110610a7457610a736113f2565b5b60200260200101519050919050565b6000606073dc3ebc37da53a644d67e5e3b5ba4eef88d969d5c73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610af157826040518060600160405280602181526020016114226021913991509150610b72565b73998cb7821e605cc16b6174e7c50e19adb2dd2fb073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610b5b57826040518060600160405280602281526020016114436022913991509150610b72565b600060405180602001604052806000815250915091505b915091565b600073dc3ebc37da53a644d67e5e3b5ba4eef88d969d5c73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480610c06575073998cb7821e605cc16b6174e7c50e19adb2dd2fb073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff811115610c4b57610c4a6113c3565b5b604051908082528060200260200182016040528015610c795781602001602082028036833780820191505090505b50905073dc3ebc37da53a644d67e5e3b5ba4eef88d969d5c81600081518110610ca557610ca46113f2565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073998cb7821e605cc16b6174e7c50e19adb2dd2fb081600181518110610d0857610d076113f2565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b610d8881610d75565b82525050565b6000610d9a8383610d7f565b60208301905092915050565b6000602082019050919050565b6000610dbe82610d49565b610dc88185610d54565b9350610dd383610d65565b8060005b83811015610e04578151610deb8882610d8e565b9750610df683610da6565b925050600181019050610dd7565b5085935050505092915050565b60006020820190508181036000830152610e2b8184610db3565b905092915050565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610e6882610e3d565b9050919050565b610e7881610e5d565b8114610e8357600080fd5b50565b600081359050610e9581610e6f565b92915050565b610ea481610d75565b8114610eaf57600080fd5b50565b600081359050610ec181610e9b565b92915050565b60008060408385031215610ede57610edd610e33565b5b6000610eec85828601610e86565b9250506020610efd85828601610eb2565b9150509250929050565b60008115159050919050565b610f1c81610f07565b82525050565b6000602082019050610f376000830184610f13565b92915050565b600060208284031215610f5357610f52610e33565b5b6000610f6184828501610e86565b91505092915050565b6000819050919050565b610f7d81610f6a565b82525050565b6000602082019050610f986000830184610f74565b92915050565b610fa781610d75565b82525050565b6000602082019050610fc26000830184610f9e565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112610fed57610fec610fc8565b5b8235905067ffffffffffffffff81111561100a57611009610fcd565b5b60208301915083602082028301111561102657611025610fd2565b5b9250929050565b6000806020838503121561104457611043610e33565b5b600083013567ffffffffffffffff81111561106257611061610e38565b5b61106e85828601610fd7565b92509250509250929050565b60008060006060848603121561109357611092610e33565b5b60006110a186828701610e86565b93505060206110b286828701610e86565b92505060406110c386828701610eb2565b9150509250925092565b6000602082840312156110e3576110e2610e33565b5b60006110f184828501610eb2565b91505092915050565b61110381610e5d565b82525050565b600060208201905061111e60008301846110fa565b92915050565b60008083601f84011261113a57611139610fc8565b5b8235905067ffffffffffffffff81111561115757611156610fcd565b5b60208301915083600182028301111561117357611172610fd2565b5b9250929050565b60008060006040848603121561119357611192610e33565b5b60006111a186828701610e86565b935050602084013567ffffffffffffffff8111156111c2576111c1610e38565b5b6111ce86828701611124565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61120f81610e5d565b82525050565b60006112218383611206565b60208301905092915050565b6000602082019050919050565b6000611245826111da565b61124f81856111e5565b935061125a836111f6565b8060005b8381101561128b5781516112728882611215565b975061127d8361122d565b92505060018101905061125e565b5085935050505092915050565b600060208201905081810360008301526112b2818461123a565b905092915050565b600080604083850312156112d1576112d0610e33565b5b60006112df85828601610e86565b92505060206112f085828601610e86565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b83811015611334578082015181840152602081019050611319565b83811115611343576000848401525b50505050565b6000601f19601f8301169050919050565b6000611365826112fa565b61136f8185611305565b935061137f818560208601611316565b61138881611349565b840191505092915050565b60006040820190506113a860008301856110fa565b81810360208301526113ba818461135a565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f76616c696461746f722e6465762e756d622e6e6574776f726b68747470733a2f2f76616c696461746f72322e6465762e756d622e6e6574776f726ba2646970667358221220a252734ced14df2318763ff3d8091c0bc6619cf3589eee33961b91360f3fc96264736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061015e5760003560e01c8062113e0814610163578063095ea7b3146101815780630db18e37146101b157806317d7de7c146101e157806318160ddd146101ff5780631aa3a0081461021d5780631d4f9ce01461022757806323b872dd1461025757806327e235e31461028757806329092d0e146102b75780632e1a7d4d146102d3578063411ff4971461030357806352b41e351461032157806370a082311461033d578063838e7c3a1461036d578063902d55a5146103895780639031d913146103a75780639f0e9484146103c5578063a15ab08d146103e3578063a39fac12146103ff578063a694fc3a1461041d578063a9059cbb14610439578063c2ee3a0814610469578063db73177714610487578063dd62ed3e146104a5578063e79a198f146104d5578063e9fad8ee146104df578063edf26d9b146104fd578063fa52c7d81461052d575b600080fd5b61016b61055e565b6040516101789190610e11565b60405180910390f35b61019b60048036038101906101969190610ec7565b61062f565b6040516101a89190610f22565b60405180910390f35b6101cb60048036038101906101c69190610f3d565b610663565b6040516101d89190610f22565b60405180910390f35b6101e9610697565b6040516101f69190610f83565b60405180910390f35b6102076106bf565b6040516102149190610fad565b60405180910390f35b6102256106e7565b005b610241600480360381019061023c919061102d565b6106e9565b60405161024e9190610f22565b60405180910390f35b610271600480360381019061026c919061107a565b61074f565b60405161027e9190610f22565b60405180910390f35b6102a1600480360381019061029c9190610f3d565b610783565b6040516102ae9190610fad565b60405180910390f35b6102d160048036038101906102cc9190610f3d565b6107aa565b005b6102ed60048036038101906102e891906110cd565b6107dc565b6040516102fa9190610f22565b60405180910390f35b61030b610810565b6040516103189190611109565b60405180910390f35b61033b600480360381019061033691906110cd565b610828565b005b61035760048036038101906103529190610f3d565b61085a565b6040516103649190610fad565b60405180910390f35b6103876004803603810190610382919061117a565b610881565b005b6103916108b3565b60405161039e9190610fad565b60405180910390f35b6103af6108d7565b6040516103bc9190610fad565b60405180910390f35b6103cd6108ff565b6040516103da9190611109565b60405180910390f35b6103fd60048036038101906103f8919061117a565b610917565b005b610407610949565b6040516104149190611298565b60405180910390f35b610437600480360381019061043291906110cd565b610958565b005b610453600480360381019061044e9190610ec7565b61098a565b6040516104609190610f22565b60405180910390f35b6104716109be565b60405161047e9190610fad565b60405180910390f35b61048f6109ca565b60405161049c9190610fad565b60405180910390f35b6104bf60048036038101906104ba91906112ba565b6109ee565b6040516104cc9190610fad565b60405180910390f35b6104dd610a22565b005b6104e7610a24565b6040516104f49190610f22565b60405180910390f35b610517600480360381019061051291906110cd565b610a58565b6040516105249190611109565b60405180910390f35b61054760048036038101906105429190610f3d565b610a83565b604051610555929190611393565b60405180910390f35b60607f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff81111561059a576105996113c3565b5b6040519080825280602002602001820160405280156105c85781602001602082028036833780820191505090505b50905060005b7f000000000000000000000000000000000000000000000000000000000000000081101561062b57670de0b6b3a7640000828281518110610612576106116113f2565b5b60200260200101818152505080806001019150506105ce565b5090565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f5374616b696e6742616e6b000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b565b6000805b838390508110156107435761072884848381811061070e5761070d6113f2565b5b90506020020160208101906107239190610f3d565b610b77565b610736576000915050610749565b80806001019150506106ed565b50600190505b92915050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061078e82610b77565b6107995760006107a3565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73998cb7821e605cc16b6174e7c50e19adb2dd2fb081565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061086582610b77565b61087057600061087a565b670de0b6b3a76400005b9050919050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b73dc3ebc37da53a644d67e5e3b5ba4eef88d969d5c81565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610953610c0d565b905090565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a62610c0d565b8281518110610a7457610a736113f2565b5b60200260200101519050919050565b6000606073dc3ebc37da53a644d67e5e3b5ba4eef88d969d5c73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610af157826040518060600160405280602181526020016114226021913991509150610b72565b73998cb7821e605cc16b6174e7c50e19adb2dd2fb073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610b5b57826040518060600160405280602281526020016114436022913991509150610b72565b600060405180602001604052806000815250915091505b915091565b600073dc3ebc37da53a644d67e5e3b5ba4eef88d969d5c73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480610c06575073998cb7821e605cc16b6174e7c50e19adb2dd2fb073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b606060007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff811115610c4b57610c4a6113c3565b5b604051908082528060200260200182016040528015610c795781602001602082028036833780820191505090505b50905073dc3ebc37da53a644d67e5e3b5ba4eef88d969d5c81600081518110610ca557610ca46113f2565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073998cb7821e605cc16b6174e7c50e19adb2dd2fb081600181518110610d0857610d076113f2565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b610d8881610d75565b82525050565b6000610d9a8383610d7f565b60208301905092915050565b6000602082019050919050565b6000610dbe82610d49565b610dc88185610d54565b9350610dd383610d65565b8060005b83811015610e04578151610deb8882610d8e565b9750610df683610da6565b925050600181019050610dd7565b5085935050505092915050565b60006020820190508181036000830152610e2b8184610db3565b905092915050565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610e6882610e3d565b9050919050565b610e7881610e5d565b8114610e8357600080fd5b50565b600081359050610e9581610e6f565b92915050565b610ea481610d75565b8114610eaf57600080fd5b50565b600081359050610ec181610e9b565b92915050565b60008060408385031215610ede57610edd610e33565b5b6000610eec85828601610e86565b9250506020610efd85828601610eb2565b9150509250929050565b60008115159050919050565b610f1c81610f07565b82525050565b6000602082019050610f376000830184610f13565b92915050565b600060208284031215610f5357610f52610e33565b5b6000610f6184828501610e86565b91505092915050565b6000819050919050565b610f7d81610f6a565b82525050565b6000602082019050610f986000830184610f74565b92915050565b610fa781610d75565b82525050565b6000602082019050610fc26000830184610f9e565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112610fed57610fec610fc8565b5b8235905067ffffffffffffffff81111561100a57611009610fcd565b5b60208301915083602082028301111561102657611025610fd2565b5b9250929050565b6000806020838503121561104457611043610e33565b5b600083013567ffffffffffffffff81111561106257611061610e38565b5b61106e85828601610fd7565b92509250509250929050565b60008060006060848603121561109357611092610e33565b5b60006110a186828701610e86565b93505060206110b286828701610e86565b92505060406110c386828701610eb2565b9150509250925092565b6000602082840312156110e3576110e2610e33565b5b60006110f184828501610eb2565b91505092915050565b61110381610e5d565b82525050565b600060208201905061111e60008301846110fa565b92915050565b60008083601f84011261113a57611139610fc8565b5b8235905067ffffffffffffffff81111561115757611156610fcd565b5b60208301915083600182028301111561117357611172610fd2565b5b9250929050565b60008060006040848603121561119357611192610e33565b5b60006111a186828701610e86565b935050602084013567ffffffffffffffff8111156111c2576111c1610e38565b5b6111ce86828701611124565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61120f81610e5d565b82525050565b60006112218383611206565b60208301905092915050565b6000602082019050919050565b6000611245826111da565b61124f81856111e5565b935061125a836111f6565b8060005b8381101561128b5781516112728882611215565b975061127d8361122d565b92505060018101905061125e565b5085935050505092915050565b600060208201905081810360008301526112b2818461123a565b905092915050565b600080604083850312156112d1576112d0610e33565b5b60006112df85828601610e86565b92505060206112f085828601610e86565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b83811015611334578082015181840152602081019050611319565b83811115611343576000848401525b50505050565b6000601f19601f8301169050919050565b6000611365826112fa565b61136f8185611305565b935061137f818560208601611316565b61138881611349565b840191505092915050565b60006040820190506113a860008301856110fa565b81810360208301526113ba818461135a565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe68747470733a2f2f76616c696461746f722e6465762e756d622e6e6574776f726b68747470733a2f2f76616c696461746f72322e6465762e756d622e6e6574776f726ba2646970667358221220a252734ced14df2318763ff3d8091c0bc6619cf3589eee33961b91360f3fc96264736f6c634300080d0033", + "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 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/dione_staging/UmbrellaFeeds.json b/deployments/dione_staging/UmbrellaFeeds.json new file mode 100644 index 0000000..7f2f8e4 --- /dev/null +++ b/deployments/dione_staging/UmbrellaFeeds.json @@ -0,0 +1,943 @@ +{ + "address": "0x3F2254bc49d2d6e8422D71cB5384fB76005558A9", + "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" + } + ], + "transactionHash": "0xa8a034ba8c87bcad1cc66a0aabf21639de04873f5e3a24de30b6aaf5c2bb351d", + "receipt": { + "to": null, + "from": "0x66f13FDceed822E74b6a1e08e082Fa699fF36454", + "contractAddress": "0x3F2254bc49d2d6e8422D71cB5384fB76005558A9", + "transactionIndex": 0, + "gasUsed": "2534549", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x29a3e3342909fef6df5d5e2537d8d7c2131e7be99437f4f35207c234dc5937aa", + "transactionHash": "0xa8a034ba8c87bcad1cc66a0aabf21639de04873f5e3a24de30b6aaf5c2bb351d", + "logs": [], + "blockNumber": 782522, + "cumulativeGasUsed": "2534549", + "status": 1, + "byzantium": true + }, + "args": [ + "0x92010E763d476A732021191562134c488ca92a1F", + 2, + 8 + ], + "numDeployments": 1, + "solcInputHash": "7f9517721aff9c6260eb58dca9f69725", + "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", + "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 + }, + "storageLayout": { + "storage": [ + { + "astId": 4239, + "contract": "contracts/onChainFeeds/UmbrellaFeeds.sol:UmbrellaFeeds", + "label": "_prices", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_bytes32,t_struct(PriceData)3365_storage)" + } + ], + "types": { + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "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)3365_storage" + }, + "t_struct(PriceData)3365_storage": { + "encoding": "inplace", + "label": "struct IUmbrellaFeeds.PriceData", + "members": [ + { + "astId": 3355, + "contract": "contracts/onChainFeeds/UmbrellaFeeds.sol:UmbrellaFeeds", + "label": "data", + "offset": 0, + "slot": "0", + "type": "t_uint8" + }, + { + "astId": 3358, + "contract": "contracts/onChainFeeds/UmbrellaFeeds.sol:UmbrellaFeeds", + "label": "heartbeat", + "offset": 1, + "slot": "0", + "type": "t_uint24" + }, + { + "astId": 3361, + "contract": "contracts/onChainFeeds/UmbrellaFeeds.sol:UmbrellaFeeds", + "label": "timestamp", + "offset": 4, + "slot": "0", + "type": "t_uint32" + }, + { + "astId": 3364, + "contract": "contracts/onChainFeeds/UmbrellaFeeds.sol:UmbrellaFeeds", + "label": "price", + "offset": 8, + "slot": "0", + "type": "t_uint128" + } + ], + "numberOfBytes": "32" + }, + "t_uint128": { + "encoding": "inplace", + "label": "uint128", + "numberOfBytes": "16" + }, + "t_uint24": { + "encoding": "inplace", + "label": "uint24", + "numberOfBytes": "3" + }, + "t_uint32": { + "encoding": "inplace", + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/deployments/dione_staging/UmbrellaFeedsReaderFactory.json b/deployments/dione_staging/UmbrellaFeedsReaderFactory.json new file mode 100644 index 0000000..13e459f --- /dev/null +++ b/deployments/dione_staging/UmbrellaFeedsReaderFactory.json @@ -0,0 +1,229 @@ +{ + "address": "0x65833489170A55374786B97C96e691949C60175a", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IRegistry", + "name": "_registry", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "EmptyAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract UmbrellaFeedsReader", + "name": "umbrellaFeedsReader", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "feedName", + "type": "string" + } + ], + "name": "NewUmbrellaFeedsReader", + "type": "event" + }, + { + "inputs": [], + "name": "REGISTRY", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_feedName", + "type": "string" + } + ], + "name": "deploy", + "outputs": [ + { + "internalType": "contract UmbrellaFeedsReader", + "name": "reader", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_feedName", + "type": "string" + } + ], + "name": "deployed", + "outputs": [ + { + "internalType": "contract UmbrellaFeedsReader", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getName", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_feedName", + "type": "string" + } + ], + "name": "hash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "readers", + "outputs": [ + { + "internalType": "contract UmbrellaFeedsReader", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0xa8d95ec0ead57cd5c7f9ee7956a747406d1dd7982a43810a1a6489148063a836", + "receipt": { + "to": null, + "from": "0x66f13FDceed822E74b6a1e08e082Fa699fF36454", + "contractAddress": "0x65833489170A55374786B97C96e691949C60175a", + "transactionIndex": 0, + "gasUsed": "2038111", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x1acca33efa6b3a21beaab23677c569cb3caa4f8daf5b2de51425c219e0af31a5", + "transactionHash": "0xa8d95ec0ead57cd5c7f9ee7956a747406d1dd7982a43810a1a6489148063a836", + "logs": [], + "blockNumber": 782523, + "cumulativeGasUsed": "2038111", + "status": 1, + "byzantium": true + }, + "args": [ + "0x92010E763d476A732021191562134c488ca92a1F" + ], + "numDeployments": 1, + "solcInputHash": "7f9517721aff9c6260eb58dca9f69725", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"_registry\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"EmptyAddress\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract UmbrellaFeedsReader\",\"name\":\"umbrellaFeedsReader\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"feedName\",\"type\":\"string\"}],\"name\":\"NewUmbrellaFeedsReader\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"REGISTRY\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_feedName\",\"type\":\"string\"}],\"name\":\"deploy\",\"outputs\":[{\"internalType\":\"contract UmbrellaFeedsReader\",\"name\":\"reader\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_feedName\",\"type\":\"string\"}],\"name\":\"deployed\",\"outputs\":[{\"internalType\":\"contract UmbrellaFeedsReader\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_feedName\",\"type\":\"string\"}],\"name\":\"hash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"readers\",\"outputs\":[{\"internalType\":\"contract UmbrellaFeedsReader\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"deploy(string)\":{\"details\":\"Method to deploy new UmbrellaFeedsReader for particular key. This deployment is optional and it can be done by anyone who needs it. Reader can be used to simplify migration from Chainlink to Umbrella. Check UmbrellaFeedsReader docs for more details. We not using minimal proxy because it does not allow for immutable variables.\",\"params\":{\"_feedName\":\"string Feed name that is registered in UmbrellaFeeds\"},\"returns\":{\"reader\":\"UmbrellaFeedsReader contract address, in case anyone wants to use it from Layer1\"}},\"getName()\":{\"details\":\"to follow Registrable interface\"}},\"stateVariables\":{\"REGISTRY\":{\"details\":\"Registry contract where list of all addresses is stored. Used to resolve newest `UmbrellaFeeds` address\"},\"readers\":{\"details\":\"list of all readers\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Factory to deploy UmbrellaFeedsReader contract\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/onChainFeeds/UmbrellaFeedsReaderFactory.sol\":\"UmbrellaFeedsReaderFactory\"},\"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/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/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\",\"keccak256\":\"0xf9417df1d6605ada8ea603592f3c5e550be763e113cb1b69a8c8fee48de73db8\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0xdcfedbd301a65355adc84bef52ea16288762b782c20624222242aa37d206d50d\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a060405234801561001057600080fd5b506040516125a33803806125a383398181016040528101906100329190610147565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610098576040517f7138356f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff168152505050610174565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610102826100d7565b9050919050565b6000610114826100f7565b9050919050565b61012481610109565b811461012f57600080fd5b50565b6000815190506101418161011b565b92915050565b60006020828403121561015d5761015c6100d2565b5b600061016b84828501610132565b91505092915050565b60805161240661019d6000396000818161018d0152818161026201526103e801526124066000f3fe60806040523480156200001157600080fd5b50600436106200006a5760003560e01c806306433b1b146200006f5780630d5befc1146200009157806317d7de7c14620000c7578063b411ee9414620000e9578063c7602316146200011f578063c7ee05191462000155575b600080fd5b620000796200018b565b604051620000889190620005c3565b60405180910390f35b620000af6004803603810190620000a9919062000756565b620001af565b604051620000be9190620007cc565b60405180910390f35b620000d1620001f5565b604051620000e0919062000804565b60405180910390f35b62000107600480360381019062000101919062000756565b6200021d565b60405162000116919062000804565b60405180910390f35b6200013d600480360381019062000137919062000756565b6200024f565b6040516200014c9190620007cc565b60405180910390f35b6200017360048036038101906200016d919062000852565b620004f7565b604051620001829190620007cc565b60405180910390f35b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806000620001bf846200021d565b815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60007f556d6272656c6c614665656473526561646572466163746f7279000000000000905090565b60008160405160200162000232919062000907565b604051602081830303815290604052805190602001209050919050565b60006200025c82620001af565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663e8f98f886040518163ffffffff1660e01b8152600401620002b99062000981565b602060405180830381865afa158015620002d7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002fd9190620009e8565b9050600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614158015620003d957508073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1663bb25b1ea6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200039b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003c19190620009e8565b73ffffffffffffffffffffffffffffffffffffffff16145b15620003e65750620004f2565b7f0000000000000000000000000000000000000000000000000000000000000000818460405162000417906200052a565b620004259392919062000a80565b604051809103906000f08015801562000442573d6000803e3d6000fd5b5091508160008062000454866200021d565b815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff167f7f5e2d33fdf12b9e483624348a7513ba1c5b0c4ecada4be7c542fc2c7e3fbe3184604051620004e8919062000ac4565b60405180910390a2505b919050565b60006020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6118e88062000ae983390190565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000620005836200057d620005778462000538565b62000558565b62000538565b9050919050565b6000620005978262000562565b9050919050565b6000620005ab826200058a565b9050919050565b620005bd816200059e565b82525050565b6000602082019050620005da6000830184620005b2565b92915050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6200064982620005fe565b810181811067ffffffffffffffff821117156200066b576200066a6200060f565b5b80604052505050565b600062000680620005e0565b90506200068e82826200063e565b919050565b600067ffffffffffffffff821115620006b157620006b06200060f565b5b620006bc82620005fe565b9050602081019050919050565b82818337600083830152505050565b6000620006ef620006e98462000693565b62000674565b9050828152602081018484840111156200070e576200070d620005f9565b5b6200071b848285620006c9565b509392505050565b600082601f8301126200073b576200073a620005f4565b5b81356200074d848260208601620006d8565b91505092915050565b6000602082840312156200076f576200076e620005ea565b5b600082013567ffffffffffffffff81111562000790576200078f620005ef565b5b6200079e8482850162000723565b91505092915050565b6000620007b4826200058a565b9050919050565b620007c681620007a7565b82525050565b6000602082019050620007e36000830184620007bb565b92915050565b6000819050919050565b620007fe81620007e9565b82525050565b60006020820190506200081b6000830184620007f3565b92915050565b6200082c81620007e9565b81146200083857600080fd5b50565b6000813590506200084c8162000821565b92915050565b6000602082840312156200086b576200086a620005ea565b5b60006200087b848285016200083b565b91505092915050565b600081519050919050565b600081905092915050565b60005b83811015620008ba5780820151818401526020810190506200089d565b83811115620008ca576000848401525b50505050565b6000620008dd8262000884565b620008e981856200088f565b9350620008fb8185602086016200089a565b80840191505092915050565b6000620009158284620008d0565b915081905092915050565b600082825260208201905092915050565b7f556d6272656c6c61466565647300000000000000000000000000000000000000600082015250565b600062000969600d8362000920565b9150620009768262000931565b602082019050919050565b600060208201905081810360008301526200099c816200095a565b9050919050565b6000620009b08262000538565b9050919050565b620009c281620009a3565b8114620009ce57600080fd5b50565b600081519050620009e281620009b7565b92915050565b60006020828403121562000a015762000a00620005ea565b5b600062000a1184828501620009d1565b91505092915050565b600062000a27826200058a565b9050919050565b62000a398162000a1a565b82525050565b600062000a4c8262000884565b62000a58818562000920565b935062000a6a8185602086016200089a565b62000a7581620005fe565b840191505092915050565b600060608201905062000a976000830186620005b2565b62000aa6602083018562000a2e565b818103604083015262000aba818462000a3f565b9050949350505050565b6000602082019050818103600083015262000ae0818462000a3f565b90509291505056fe6101006040523480156200001257600080fd5b50604051620018e8380380620018e8833981810160405281019062000038919062000569565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036200009f576040517f7138356f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250508173ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff168152505080600090805190602001906200011f9291906200025e565b508173ffffffffffffffffffffffffffffffffffffffff16632e0f26256040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200016c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000192919062000622565b60ff1660e08160ff1681525050600081604051602001620001b49190620006a1565b6040516020818303038152906040528051906020012090508060c081815250508273ffffffffffffffffffffffffffffffffffffffff166343fa6211826040518263ffffffff1660e01b81526004016200020f9190620006d5565b608060405180830381865afa1580156200022d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200025391906200084a565b5050505050620008e0565b8280546200026c90620008ab565b90600052602060002090601f016020900481019282620002905760008555620002dc565b82601f10620002ab57805160ff1916838001178555620002dc565b82800160010185558215620002dc579182015b82811115620002db578251825591602001919060010190620002be565b5b509050620002eb9190620002ef565b5090565b5b808211156200030a576000816000905550600101620002f0565b5090565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200034f8262000322565b9050919050565b6000620003638262000342565b9050919050565b620003758162000356565b81146200038157600080fd5b50565b60008151905062000395816200036a565b92915050565b6000620003a88262000342565b9050919050565b620003ba816200039b565b8114620003c657600080fd5b50565b600081519050620003da81620003af565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6200043582620003ea565b810181811067ffffffffffffffff82111715620004575762000456620003fb565b5b80604052505050565b60006200046c6200030e565b90506200047a82826200042a565b919050565b600067ffffffffffffffff8211156200049d576200049c620003fb565b5b620004a882620003ea565b9050602081019050919050565b60005b83811015620004d5578082015181840152602081019050620004b8565b83811115620004e5576000848401525b50505050565b600062000502620004fc846200047f565b62000460565b905082815260208101848484011115620005215762000520620003e5565b5b6200052e848285620004b5565b509392505050565b600082601f8301126200054e576200054d620003e0565b5b815162000560848260208601620004eb565b91505092915050565b60008060006060848603121562000585576200058462000318565b5b6000620005958682870162000384565b9350506020620005a886828701620003c9565b925050604084015167ffffffffffffffff811115620005cc57620005cb6200031d565b5b620005da8682870162000536565b9150509250925092565b600060ff82169050919050565b620005fc81620005e4565b81146200060857600080fd5b50565b6000815190506200061c81620005f1565b92915050565b6000602082840312156200063b576200063a62000318565b5b60006200064b848285016200060b565b91505092915050565b600081519050919050565b600081905092915050565b6000620006778262000654565b6200068381856200065f565b935062000695818560208601620004b5565b80840191505092915050565b6000620006af82846200066a565b915081905092915050565b6000819050919050565b620006cf81620006ba565b82525050565b6000602082019050620006ec6000830184620006c4565b92915050565b600080fd5b600062ffffff82169050919050565b6200071181620006f7565b81146200071d57600080fd5b50565b600081519050620007318162000706565b92915050565b600063ffffffff82169050919050565b620007528162000737565b81146200075e57600080fd5b50565b600081519050620007728162000747565b92915050565b60006fffffffffffffffffffffffffffffffff82169050919050565b6200079f8162000778565b8114620007ab57600080fd5b50565b600081519050620007bf8162000794565b92915050565b600060808284031215620007de57620007dd620006f2565b5b620007ea608062000460565b90506000620007fc848285016200060b565b6000830152506020620008128482850162000720565b6020830152506040620008288482850162000761565b60408301525060606200083e84828501620007ae565b60608301525092915050565b60006080828403121562000863576200086262000318565b5b60006200087384828501620007c5565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680620008c457607f821691505b602082108103620008da57620008d96200087c565b5b50919050565b60805160a05160c05160e051610f966200095260003960006101bd015260008181610197015281816103b5015281816105d801526107a20152600081816102da01528181610376015281816105690152610701015260008181610173015281816104cf01526106670152610f966000f3fe608060405234801561001057600080fd5b50600436106100785760003560e01c806306433b1b1461007d5780632dc387b31461009b578063313ce567146100b95780637284e416146100d757806376ded135146100f5578063a4a2816814610113578063bb25b1ea14610131578063feaf968c1461014f575b600080fd5b610085610171565b60405161009291906108eb565b60405180910390f35b6100a3610195565b6040516100b0919061091f565b60405180910390f35b6100c16101b9565b6040516100ce9190610956565b60405180910390f35b6100df6101e1565b6040516100ec9190610a0a565b60405180910390f35b6100fd61026f565b60405161010a9190610af8565b60405180910390f35b61011b6102a6565b6040516101289190610af8565b60405180910390f35b6101396102d8565b6040516101469190610b34565b60405180910390f35b6101576102fc565b604051610168959493929190610ba6565b60405180910390f35b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b600080546101ee90610c28565b80601f016020809104026020016040519081016040528092919081815260200182805461021a90610c28565b80156102675780601f1061023c57610100808354040283529160200191610267565b820191906000526020600020905b81548152906001019060200180831161024a57829003601f168201915b505050505081565b610277610824565b61027f610369565b90506000816040015163ffffffff16036102a25761029b6104c3565b90506102a3565b5b90565b6102ae610824565b6102b6610369565b90506000816040015163ffffffff16036102d5576102d261065b565b90505b90565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060008060008061030d610369565b90506000816040015163ffffffff160361032c5761032961065b565b90505b600081606001516fffffffffffffffffffffffffffffffff166000836040015160008163ffffffff16915095509550955095509550509091929394565b610371610824565b6000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166360846bc660e01b7f00000000000000000000000000000000000000000000000000000000000000006040516024016103e4919061091f565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161044e9190610ca0565b600060405180830381855afa9150503d8060008114610489576040519150601f19603f3d011682016040523d82523d6000602084013e61048e565b606091505b50915091508180156104a257506000815114155b156104be57808060200190518101906104bb9190610e6e565b92505b505090565b6104cb610824565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663e8f98f886040518163ffffffff1660e01b815260040161052490610ee7565b602060405180830381865afa158015610541573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105659190610f33565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610657578073ffffffffffffffffffffffffffffffffffffffff166360846bc67f00000000000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b8152600401610613919061091f565b608060405180830381865afa158015610630573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106549190610e6e565b91505b5090565b610663610824565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663e8f98f886040518163ffffffff1660e01b81526004016106bc90610ee7565b602060405180830381865afa1580156106d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106fd9190610f33565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610784576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166343fa62117f00000000000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b81526004016107dd919061091f565b608060405180830381865afa1580156107fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061081e9190610e6e565b91505090565b6040518060800160405280600060ff168152602001600062ffffff168152602001600063ffffffff16815260200160006fffffffffffffffffffffffffffffffff1681525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006108b16108ac6108a78461086c565b61088c565b61086c565b9050919050565b60006108c382610896565b9050919050565b60006108d5826108b8565b9050919050565b6108e5816108ca565b82525050565b600060208201905061090060008301846108dc565b92915050565b6000819050919050565b61091981610906565b82525050565b60006020820190506109346000830184610910565b92915050565b600060ff82169050919050565b6109508161093a565b82525050565b600060208201905061096b6000830184610947565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156109ab578082015181840152602081019050610990565b838111156109ba576000848401525b50505050565b6000601f19601f8301169050919050565b60006109dc82610971565b6109e6818561097c565b93506109f681856020860161098d565b6109ff816109c0565b840191505092915050565b60006020820190508181036000830152610a2481846109d1565b905092915050565b610a358161093a565b82525050565b600062ffffff82169050919050565b610a5381610a3b565b82525050565b600063ffffffff82169050919050565b610a7281610a59565b82525050565b60006fffffffffffffffffffffffffffffffff82169050919050565b610a9d81610a78565b82525050565b608082016000820151610ab96000850182610a2c565b506020820151610acc6020850182610a4a565b506040820151610adf6040850182610a69565b506060820151610af26060850182610a94565b50505050565b6000608082019050610b0d6000830184610aa3565b92915050565b6000610b1e8261086c565b9050919050565b610b2e81610b13565b82525050565b6000602082019050610b496000830184610b25565b92915050565b600069ffffffffffffffffffff82169050919050565b610b6e81610b4f565b82525050565b6000819050919050565b610b8781610b74565b82525050565b6000819050919050565b610ba081610b8d565b82525050565b600060a082019050610bbb6000830188610b65565b610bc86020830187610b7e565b610bd56040830186610b97565b610be26060830185610b97565b610bef6080830184610b65565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680610c4057607f821691505b602082108103610c5357610c52610bf9565b5b50919050565b600081519050919050565b600081905092915050565b6000610c7a82610c59565b610c848185610c64565b9350610c9481856020860161098d565b80840191505092915050565b6000610cac8284610c6f565b915081905092915050565b6000604051905090565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610d03826109c0565b810181811067ffffffffffffffff82111715610d2257610d21610ccb565b5b80604052505050565b6000610d35610cb7565b9050610d418282610cfa565b919050565b610d4f8161093a565b8114610d5a57600080fd5b50565b600081519050610d6c81610d46565b92915050565b610d7b81610a3b565b8114610d8657600080fd5b50565b600081519050610d9881610d72565b92915050565b610da781610a59565b8114610db257600080fd5b50565b600081519050610dc481610d9e565b92915050565b610dd381610a78565b8114610dde57600080fd5b50565b600081519050610df081610dca565b92915050565b600060808284031215610e0c57610e0b610cc6565b5b610e166080610d2b565b90506000610e2684828501610d5d565b6000830152506020610e3a84828501610d89565b6020830152506040610e4e84828501610db5565b6040830152506060610e6284828501610de1565b60608301525092915050565b600060808284031215610e8457610e83610cc1565b5b6000610e9284828501610df6565b91505092915050565b7f556d6272656c6c61466565647300000000000000000000000000000000000000600082015250565b6000610ed1600d8361097c565b9150610edc82610e9b565b602082019050919050565b60006020820190508181036000830152610f0081610ec4565b9050919050565b610f1081610b13565b8114610f1b57600080fd5b50565b600081519050610f2d81610f07565b92915050565b600060208284031215610f4957610f48610cc1565b5b6000610f5784828501610f1e565b9150509291505056fea2646970667358221220cab64fd82e235637ccebdb365366012a5e08bc149a1b3facd9cd40ab2db8d53a64736f6c634300080d0033a2646970667358221220285e5edb451c5cf1ca0e6c03fb7a78d7d336c4ce2b37185346e7243719a4236b64736f6c634300080d0033", + "deployedBytecode": "0x60806040523480156200001157600080fd5b50600436106200006a5760003560e01c806306433b1b146200006f5780630d5befc1146200009157806317d7de7c14620000c7578063b411ee9414620000e9578063c7602316146200011f578063c7ee05191462000155575b600080fd5b620000796200018b565b604051620000889190620005c3565b60405180910390f35b620000af6004803603810190620000a9919062000756565b620001af565b604051620000be9190620007cc565b60405180910390f35b620000d1620001f5565b604051620000e0919062000804565b60405180910390f35b62000107600480360381019062000101919062000756565b6200021d565b60405162000116919062000804565b60405180910390f35b6200013d600480360381019062000137919062000756565b6200024f565b6040516200014c9190620007cc565b60405180910390f35b6200017360048036038101906200016d919062000852565b620004f7565b604051620001829190620007cc565b60405180910390f35b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806000620001bf846200021d565b815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60007f556d6272656c6c614665656473526561646572466163746f7279000000000000905090565b60008160405160200162000232919062000907565b604051602081830303815290604052805190602001209050919050565b60006200025c82620001af565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663e8f98f886040518163ffffffff1660e01b8152600401620002b99062000981565b602060405180830381865afa158015620002d7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002fd9190620009e8565b9050600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614158015620003d957508073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1663bb25b1ea6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200039b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003c19190620009e8565b73ffffffffffffffffffffffffffffffffffffffff16145b15620003e65750620004f2565b7f0000000000000000000000000000000000000000000000000000000000000000818460405162000417906200052a565b620004259392919062000a80565b604051809103906000f08015801562000442573d6000803e3d6000fd5b5091508160008062000454866200021d565b815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff167f7f5e2d33fdf12b9e483624348a7513ba1c5b0c4ecada4be7c542fc2c7e3fbe3184604051620004e8919062000ac4565b60405180910390a2505b919050565b60006020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6118e88062000ae983390190565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000620005836200057d620005778462000538565b62000558565b62000538565b9050919050565b6000620005978262000562565b9050919050565b6000620005ab826200058a565b9050919050565b620005bd816200059e565b82525050565b6000602082019050620005da6000830184620005b2565b92915050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6200064982620005fe565b810181811067ffffffffffffffff821117156200066b576200066a6200060f565b5b80604052505050565b600062000680620005e0565b90506200068e82826200063e565b919050565b600067ffffffffffffffff821115620006b157620006b06200060f565b5b620006bc82620005fe565b9050602081019050919050565b82818337600083830152505050565b6000620006ef620006e98462000693565b62000674565b9050828152602081018484840111156200070e576200070d620005f9565b5b6200071b848285620006c9565b509392505050565b600082601f8301126200073b576200073a620005f4565b5b81356200074d848260208601620006d8565b91505092915050565b6000602082840312156200076f576200076e620005ea565b5b600082013567ffffffffffffffff81111562000790576200078f620005ef565b5b6200079e8482850162000723565b91505092915050565b6000620007b4826200058a565b9050919050565b620007c681620007a7565b82525050565b6000602082019050620007e36000830184620007bb565b92915050565b6000819050919050565b620007fe81620007e9565b82525050565b60006020820190506200081b6000830184620007f3565b92915050565b6200082c81620007e9565b81146200083857600080fd5b50565b6000813590506200084c8162000821565b92915050565b6000602082840312156200086b576200086a620005ea565b5b60006200087b848285016200083b565b91505092915050565b600081519050919050565b600081905092915050565b60005b83811015620008ba5780820151818401526020810190506200089d565b83811115620008ca576000848401525b50505050565b6000620008dd8262000884565b620008e981856200088f565b9350620008fb8185602086016200089a565b80840191505092915050565b6000620009158284620008d0565b915081905092915050565b600082825260208201905092915050565b7f556d6272656c6c61466565647300000000000000000000000000000000000000600082015250565b600062000969600d8362000920565b9150620009768262000931565b602082019050919050565b600060208201905081810360008301526200099c816200095a565b9050919050565b6000620009b08262000538565b9050919050565b620009c281620009a3565b8114620009ce57600080fd5b50565b600081519050620009e281620009b7565b92915050565b60006020828403121562000a015762000a00620005ea565b5b600062000a1184828501620009d1565b91505092915050565b600062000a27826200058a565b9050919050565b62000a398162000a1a565b82525050565b600062000a4c8262000884565b62000a58818562000920565b935062000a6a8185602086016200089a565b62000a7581620005fe565b840191505092915050565b600060608201905062000a976000830186620005b2565b62000aa6602083018562000a2e565b818103604083015262000aba818462000a3f565b9050949350505050565b6000602082019050818103600083015262000ae0818462000a3f565b90509291505056fe6101006040523480156200001257600080fd5b50604051620018e8380380620018e8833981810160405281019062000038919062000569565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036200009f576040517f7138356f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250508173ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff168152505080600090805190602001906200011f9291906200025e565b508173ffffffffffffffffffffffffffffffffffffffff16632e0f26256040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200016c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000192919062000622565b60ff1660e08160ff1681525050600081604051602001620001b49190620006a1565b6040516020818303038152906040528051906020012090508060c081815250508273ffffffffffffffffffffffffffffffffffffffff166343fa6211826040518263ffffffff1660e01b81526004016200020f9190620006d5565b608060405180830381865afa1580156200022d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200025391906200084a565b5050505050620008e0565b8280546200026c90620008ab565b90600052602060002090601f016020900481019282620002905760008555620002dc565b82601f10620002ab57805160ff1916838001178555620002dc565b82800160010185558215620002dc579182015b82811115620002db578251825591602001919060010190620002be565b5b509050620002eb9190620002ef565b5090565b5b808211156200030a576000816000905550600101620002f0565b5090565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200034f8262000322565b9050919050565b6000620003638262000342565b9050919050565b620003758162000356565b81146200038157600080fd5b50565b60008151905062000395816200036a565b92915050565b6000620003a88262000342565b9050919050565b620003ba816200039b565b8114620003c657600080fd5b50565b600081519050620003da81620003af565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6200043582620003ea565b810181811067ffffffffffffffff82111715620004575762000456620003fb565b5b80604052505050565b60006200046c6200030e565b90506200047a82826200042a565b919050565b600067ffffffffffffffff8211156200049d576200049c620003fb565b5b620004a882620003ea565b9050602081019050919050565b60005b83811015620004d5578082015181840152602081019050620004b8565b83811115620004e5576000848401525b50505050565b600062000502620004fc846200047f565b62000460565b905082815260208101848484011115620005215762000520620003e5565b5b6200052e848285620004b5565b509392505050565b600082601f8301126200054e576200054d620003e0565b5b815162000560848260208601620004eb565b91505092915050565b60008060006060848603121562000585576200058462000318565b5b6000620005958682870162000384565b9350506020620005a886828701620003c9565b925050604084015167ffffffffffffffff811115620005cc57620005cb6200031d565b5b620005da8682870162000536565b9150509250925092565b600060ff82169050919050565b620005fc81620005e4565b81146200060857600080fd5b50565b6000815190506200061c81620005f1565b92915050565b6000602082840312156200063b576200063a62000318565b5b60006200064b848285016200060b565b91505092915050565b600081519050919050565b600081905092915050565b6000620006778262000654565b6200068381856200065f565b935062000695818560208601620004b5565b80840191505092915050565b6000620006af82846200066a565b915081905092915050565b6000819050919050565b620006cf81620006ba565b82525050565b6000602082019050620006ec6000830184620006c4565b92915050565b600080fd5b600062ffffff82169050919050565b6200071181620006f7565b81146200071d57600080fd5b50565b600081519050620007318162000706565b92915050565b600063ffffffff82169050919050565b620007528162000737565b81146200075e57600080fd5b50565b600081519050620007728162000747565b92915050565b60006fffffffffffffffffffffffffffffffff82169050919050565b6200079f8162000778565b8114620007ab57600080fd5b50565b600081519050620007bf8162000794565b92915050565b600060808284031215620007de57620007dd620006f2565b5b620007ea608062000460565b90506000620007fc848285016200060b565b6000830152506020620008128482850162000720565b6020830152506040620008288482850162000761565b60408301525060606200083e84828501620007ae565b60608301525092915050565b60006080828403121562000863576200086262000318565b5b60006200087384828501620007c5565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680620008c457607f821691505b602082108103620008da57620008d96200087c565b5b50919050565b60805160a05160c05160e051610f966200095260003960006101bd015260008181610197015281816103b5015281816105d801526107a20152600081816102da01528181610376015281816105690152610701015260008181610173015281816104cf01526106670152610f966000f3fe608060405234801561001057600080fd5b50600436106100785760003560e01c806306433b1b1461007d5780632dc387b31461009b578063313ce567146100b95780637284e416146100d757806376ded135146100f5578063a4a2816814610113578063bb25b1ea14610131578063feaf968c1461014f575b600080fd5b610085610171565b60405161009291906108eb565b60405180910390f35b6100a3610195565b6040516100b0919061091f565b60405180910390f35b6100c16101b9565b6040516100ce9190610956565b60405180910390f35b6100df6101e1565b6040516100ec9190610a0a565b60405180910390f35b6100fd61026f565b60405161010a9190610af8565b60405180910390f35b61011b6102a6565b6040516101289190610af8565b60405180910390f35b6101396102d8565b6040516101469190610b34565b60405180910390f35b6101576102fc565b604051610168959493929190610ba6565b60405180910390f35b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b600080546101ee90610c28565b80601f016020809104026020016040519081016040528092919081815260200182805461021a90610c28565b80156102675780601f1061023c57610100808354040283529160200191610267565b820191906000526020600020905b81548152906001019060200180831161024a57829003601f168201915b505050505081565b610277610824565b61027f610369565b90506000816040015163ffffffff16036102a25761029b6104c3565b90506102a3565b5b90565b6102ae610824565b6102b6610369565b90506000816040015163ffffffff16036102d5576102d261065b565b90505b90565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060008060008061030d610369565b90506000816040015163ffffffff160361032c5761032961065b565b90505b600081606001516fffffffffffffffffffffffffffffffff166000836040015160008163ffffffff16915095509550955095509550509091929394565b610371610824565b6000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166360846bc660e01b7f00000000000000000000000000000000000000000000000000000000000000006040516024016103e4919061091f565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161044e9190610ca0565b600060405180830381855afa9150503d8060008114610489576040519150601f19603f3d011682016040523d82523d6000602084013e61048e565b606091505b50915091508180156104a257506000815114155b156104be57808060200190518101906104bb9190610e6e565b92505b505090565b6104cb610824565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663e8f98f886040518163ffffffff1660e01b815260040161052490610ee7565b602060405180830381865afa158015610541573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105659190610f33565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610657578073ffffffffffffffffffffffffffffffffffffffff166360846bc67f00000000000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b8152600401610613919061091f565b608060405180830381865afa158015610630573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106549190610e6e565b91505b5090565b610663610824565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663e8f98f886040518163ffffffff1660e01b81526004016106bc90610ee7565b602060405180830381865afa1580156106d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106fd9190610f33565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610784576040517f15647ae900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166343fa62117f00000000000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b81526004016107dd919061091f565b608060405180830381865afa1580156107fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061081e9190610e6e565b91505090565b6040518060800160405280600060ff168152602001600062ffffff168152602001600063ffffffff16815260200160006fffffffffffffffffffffffffffffffff1681525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006108b16108ac6108a78461086c565b61088c565b61086c565b9050919050565b60006108c382610896565b9050919050565b60006108d5826108b8565b9050919050565b6108e5816108ca565b82525050565b600060208201905061090060008301846108dc565b92915050565b6000819050919050565b61091981610906565b82525050565b60006020820190506109346000830184610910565b92915050565b600060ff82169050919050565b6109508161093a565b82525050565b600060208201905061096b6000830184610947565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156109ab578082015181840152602081019050610990565b838111156109ba576000848401525b50505050565b6000601f19601f8301169050919050565b60006109dc82610971565b6109e6818561097c565b93506109f681856020860161098d565b6109ff816109c0565b840191505092915050565b60006020820190508181036000830152610a2481846109d1565b905092915050565b610a358161093a565b82525050565b600062ffffff82169050919050565b610a5381610a3b565b82525050565b600063ffffffff82169050919050565b610a7281610a59565b82525050565b60006fffffffffffffffffffffffffffffffff82169050919050565b610a9d81610a78565b82525050565b608082016000820151610ab96000850182610a2c565b506020820151610acc6020850182610a4a565b506040820151610adf6040850182610a69565b506060820151610af26060850182610a94565b50505050565b6000608082019050610b0d6000830184610aa3565b92915050565b6000610b1e8261086c565b9050919050565b610b2e81610b13565b82525050565b6000602082019050610b496000830184610b25565b92915050565b600069ffffffffffffffffffff82169050919050565b610b6e81610b4f565b82525050565b6000819050919050565b610b8781610b74565b82525050565b6000819050919050565b610ba081610b8d565b82525050565b600060a082019050610bbb6000830188610b65565b610bc86020830187610b7e565b610bd56040830186610b97565b610be26060830185610b97565b610bef6080830184610b65565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680610c4057607f821691505b602082108103610c5357610c52610bf9565b5b50919050565b600081519050919050565b600081905092915050565b6000610c7a82610c59565b610c848185610c64565b9350610c9481856020860161098d565b80840191505092915050565b6000610cac8284610c6f565b915081905092915050565b6000604051905090565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610d03826109c0565b810181811067ffffffffffffffff82111715610d2257610d21610ccb565b5b80604052505050565b6000610d35610cb7565b9050610d418282610cfa565b919050565b610d4f8161093a565b8114610d5a57600080fd5b50565b600081519050610d6c81610d46565b92915050565b610d7b81610a3b565b8114610d8657600080fd5b50565b600081519050610d9881610d72565b92915050565b610da781610a59565b8114610db257600080fd5b50565b600081519050610dc481610d9e565b92915050565b610dd381610a78565b8114610dde57600080fd5b50565b600081519050610df081610dca565b92915050565b600060808284031215610e0c57610e0b610cc6565b5b610e166080610d2b565b90506000610e2684828501610d5d565b6000830152506020610e3a84828501610d89565b6020830152506040610e4e84828501610db5565b6040830152506060610e6284828501610de1565b60608301525092915050565b600060808284031215610e8457610e83610cc1565b5b6000610e9284828501610df6565b91505092915050565b7f556d6272656c6c61466565647300000000000000000000000000000000000000600082015250565b6000610ed1600d8361097c565b9150610edc82610e9b565b602082019050919050565b60006020820190508181036000830152610f0081610ec4565b9050919050565b610f1081610b13565b8114610f1b57600080fd5b50565b600081519050610f2d81610f07565b92915050565b600060208284031215610f4957610f48610cc1565b5b6000610f5784828501610f1e565b9150509291505056fea2646970667358221220cab64fd82e235637ccebdb365366012a5e08bc149a1b3facd9cd40ab2db8d53a64736f6c634300080d0033a2646970667358221220285e5edb451c5cf1ca0e6c03fb7a78d7d336c4ce2b37185346e7243719a4236b64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": { + "deploy(string)": { + "details": "Method to deploy new UmbrellaFeedsReader for particular key. This deployment is optional and it can be done by anyone who needs it. Reader can be used to simplify migration from Chainlink to Umbrella. Check UmbrellaFeedsReader docs for more details. We not using minimal proxy because it does not allow for immutable variables.", + "params": { + "_feedName": "string Feed name that is registered in UmbrellaFeeds" + }, + "returns": { + "reader": "UmbrellaFeedsReader contract address, in case anyone wants to use it from Layer1" + } + }, + "getName()": { + "details": "to follow Registrable interface" + } + }, + "stateVariables": { + "REGISTRY": { + "details": "Registry contract where list of all addresses is stored. Used to resolve newest `UmbrellaFeeds` address" + }, + "readers": { + "details": "list of all readers" + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "notice": "Factory to deploy UmbrellaFeedsReader contract", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 5224, + "contract": "contracts/onChainFeeds/UmbrellaFeedsReaderFactory.sol:UmbrellaFeedsReaderFactory", + "label": "readers", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_bytes32,t_contract(UmbrellaFeedsReader)5208)" + } + ], + "types": { + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(UmbrellaFeedsReader)5208": { + "encoding": "inplace", + "label": "contract UmbrellaFeedsReader", + "numberOfBytes": "20" + }, + "t_mapping(t_bytes32,t_contract(UmbrellaFeedsReader)5208)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => contract UmbrellaFeedsReader)", + "numberOfBytes": "32", + "value": "t_contract(UmbrellaFeedsReader)5208" + } + } + } +} \ No newline at end of file diff --git a/deployments/dione_staging/solcInputs/7f9517721aff9c6260eb58dca9f69725.json b/deployments/dione_staging/solcInputs/7f9517721aff9c6260eb58dca9f69725.json new file mode 100644 index 0000000..31d33b9 --- /dev/null +++ b/deployments/dione_staging/solcInputs/7f9517721aff9c6260eb58dca9f69725.json @@ -0,0 +1,122 @@ +{ + "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/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/hardhat.config.ts b/hardhat.config.ts index 0a4a49c..19f80a7 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -34,7 +34,7 @@ import { BNB, BNB_PRODUCTION, BNB_SANDBOX, - BNB_STAGING, BOB_PRODUCTION, BOB_STAGING, + BNB_STAGING, BOB_PRODUCTION, BOB_STAGING, DIONE_STAGING, ETH, ETH_PRODUCTION, ETH_SANDBOX, ETH_SEPOLIA, @@ -370,6 +370,12 @@ const config: HardhatUserConfig = { chainId: getProviderData(_5IRE_SANDBOX).chainId, gasPrice: 'auto' }, + dione_staging: { + url: getProviderData(DIONE_STAGING).url, + accounts: getPrivateKeys(LOCALHOST), + chainId: getProviderData(DIONE_STAGING).chainId, + gasPrice: 'auto' + }, _5ire_production: { url: getProviderData(_5IRE_PRODUCTION).url, accounts: getPrivateKeys(PROD_PK),